Python : 현재 실행중인 스크립트를 기준으로 sys.path에 추가하는 가장 좋은 방법


99

스크립트로 가득 찬 디렉토리가 있습니다 (예 :) project/bin. 또한 라이브러리가 있으며 project/lib스크립트가 자동으로로드하기를 원합니다. 이것은 내가 일반적으로 각 스크립트의 상단에서 사용하는 것입니다.

#!/usr/bin/python
from os.path import dirname, realpath, sep, pardir
import sys
sys.path.append(dirname(realpath(__file__)) + sep + pardir + sep + "lib")

# ... now the real code
import mylib

이것은 번거롭고 추악하며 모든 파일의 시작 부분에 붙여 넣어야합니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

정말로 내가 바라는 것은 다음과 같이 부드러운 것입니다.

#!/usr/bin/python
import sys.path
from os.path import pardir, sep
sys.path.append_relative(pardir + sep + "lib")

import mylib

또는 더 좋은 것은 내 편집자 (또는 커밋 액세스 권한이있는 다른 사람)가 정리 프로세스의 일부로 가져 오기 순서를 변경하기로 결정할 때 깨지지 않는 것입니다.

#!/usr/bin/python --relpath_append ../lib
import mylib

그것은 non-posix 플랫폼으로 직접 이식되지는 않지만 모든 것을 깨끗하게 유지합니다.


답변:


26

각 파일을 편집하고 싶지 않은 경우

  • 일반 파이썬 libray처럼 라이브러리를 설치
    하거나
  • 설정 PYTHONPATH에lib

또는 각 파일에 한 줄을 추가하려면 맨 위에 import 문을 추가하십시오.

import import_my_lib

import_my_lib.pybin에 보관 하고 원하는 import_my_lib대로 파이썬 경로를 올바르게 설정할 수 lib있습니다.


118

이것이 내가 사용하는 것입니다.

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))

2
다른 경로로 재정의되지 않도록 sys.path.insert (0, ..)를 수행합니다.
— John Jiang

이것을 자동으로 실행할 방법이 정말로 없습니까?
— Denis de Bernardy 19.07.08

1
이것은 약간 위험합니다. 경우 __file__현재 작업 디렉토리에 대한 상대 파일 이름 상대가 (예 setup.py), 다음 os.path.dirname(__file__)될 것입니다 빈 문자열입니다. 이과를 들어 존 지앙에 의해 제기 된 유사한 문제 , ekhumoro 의 일반적인 목적의 솔루션을 강하게 바람직하다.
— Cecil Curry

29

나는 사용하고있다 :

import sys,os
sys.path.append(os.getcwd())

5
나는 자주한다sys.path.append('.')
— kimbo

1
스크립트가 다른 디렉토리에서 실행되면 어떻게됩니까? 예를 들어 전체 시스템 경로를 제공하여 루트 디렉토리에서? os.getcwd ()는 "/"를 반환합니다
— obayhan

2
이러지 마세요. 현재 작업 디렉토리 (CWD)이되어 하지 특히 당신은 확실히 멀리 마일 오는 봤어야 예측할 가장자리의 경우 아래 - 당신이 생각하는 것을 보장. __file__준 정신적 인 개발자처럼 참조 하세요.
— Cecil Curry

14

다음을 포함하는 래퍼 모듈을 만듭니다 project/bin/lib.

import sys, os

sys.path.insert(0, os.path.join(
    os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib'))

import mylib

del sys.path[0], sys, os

그런 다음 스크립트 상단의 모든 흠집을 다음으로 바꿀 수 있습니다.

#!/usr/bin/python
from lib import mylib

9

어떤 방식 으로든 스크립트 내용을 변경하지 않으려면 현재 작업 디렉토리 .를 $ PYTHONPATH 앞에 추가 하십시오 (아래 예제 참조).

PYTHONPATH=.:$PYTHONPATH alembic revision --autogenerate -m "First revision"

그리고 그것을 하루라고!


docs.python.org/3/tutorial/modules.html#the-module-search-path 는 "sys.path는 다음 위치에서 초기화됩니다 .- 입력 스크립트를 포함하는 디렉토리". 사실이 아니라고 생각합니다.

특히 .envrc에서이 작업을 수행하는 경향이 있으므로 direnv를 사용하면 자동으로 격리됩니다.
— EdvardM

8

파이썬 3.4
이상 사용하기 cx_freeze 사용 금지 또는 IDLE 사용. 😃

import sys
from pathlib import Path

sys.path.append(Path(__file__).parent / "lib")

Python2 호환 : import pathlib import os sys.path.append (os.path.dirname ( file ))
— michael

5

python -m관련 루트 디렉토리에서 스크립트를 실행할 수 있습니다 . 그리고 "모듈 경로"를 인수로 전달하십시오.

예: $ python -m module.sub_module.main # Notice there is no '.py' at the end.


다른 예시:

$ tree  # Given this file structure
.
├── bar
│   ├── __init__.py
│   └── mod.py
└── foo
    ├── __init__.py
    └── main.py

$ cat foo/main.py
from bar.mod import print1
print1()

$ cat bar/mod.py
def print1():
    print('In bar/mod.py')

$ python foo/main.py  # This gives an error
Traceback (most recent call last):
  File "foo/main.py", line 1, in <module>
    from bar.mod import print1
ImportError: No module named bar.mod

$ python -m foo.main  # But this succeeds
In bar/mod.py

1
m 스위치를 사용하는 것이 권장되는 방법이며 시스템 경로 해킹이 아닙니다.
— Mr_and_Mrs_D

4

제공된 모든 답변에는 "이 마법의 주문을 스크립트 시작 부분에 추가하십시오. 코드 한두 줄로 무엇을 할 수 있는지 확인하십시오."라고 요약 할 수있는 문제가 있습니다. 가능한 모든 상황에서 작동하지는 않습니다!

예를 들어, 그러한 마법 주문 중 하나는 file을 사용 합니다 . 불행히도 cx_Freeze를 사용하여 스크립트를 패키징하거나 IDLE을 사용하는 경우 예외가 발생합니다.

또 다른 마법의 주문은 os.getcwd ()를 사용합니다. 이것은 명령 프롬프트에서 스크립트를 실행하고 스크립트가 포함 된 디렉토리가 현재 작업 디렉토리 (즉, 스크립트를 실행하기 전에 cd 명령을 사용하여 디렉토리로 변경) 인 경우에만 작동합니다. 어 신! Python 스크립트가 PATH 어딘가에 있고 단순히 스크립트 파일의 이름을 입력하여 실행 한 경우 이것이 작동하지 않는 이유를 설명 할 필요가 없기를 바랍니다.

다행히도 내가 테스트 한 모든 경우에 효과가있는 마법의 주문이 있습니다. 불행히도 마법의 주문은 코드 한두 줄 이상입니다.

import inspect
import os
import sys

# Add script directory to sys.path.
# This is complicated due to the fact that __file__ is not always defined.

def GetScriptDirectory():
    if hasattr(GetScriptDirectory, "dir"):
        return GetScriptDirectory.dir
    module_path = ""
    try:
        # The easy way. Just use __file__.
        # Unfortunately, __file__ is not available when cx_freeze is used or in IDLE.
        module_path = __file__
    except NameError:
        if len(sys.argv) > 0 and len(sys.argv[0]) > 0 and os.path.isabs(sys.argv[0]):
            module_path = sys.argv[0]
        else:
            module_path = os.path.abspath(inspect.getfile(GetScriptDirectory))
            if not os.path.exists(module_path):
                # If cx_freeze is used the value of the module_path variable at this point is in the following format.
                # {PathToExeFile}\{NameOfPythonSourceFile}. This makes it necessary to strip off the file name to get the correct
                # path.
                module_path = os.path.dirname(module_path)
    GetScriptDirectory.dir = os.path.dirname(module_path)
    return GetScriptDirectory.dir

sys.path.append(os.path.join(GetScriptDirectory(), "lib"))
print(GetScriptDirectory())
print(sys.path)

보시다시피 이것은 쉬운 일이 아닙니다!


0

이것은 나를 위해 가장 잘 작동합니다. 사용하다:

os.path.abspath('')

Mac에서는 다음과 같이 인쇄됩니다.

'/Users/<your username>/<path_to_where_you_at>'

현재 wd에 대한 abs 경로를 얻으려면 다음과 같이 원하는 경우 올라갈 수 있기 때문에 이것이 더 좋습니다.

os.path.abspath('../')

그리고 지금:

 '/Users/<your username>/'

따라서 utils여기에서 가져 오려면 '/Users/<your username>/'
남은 작업은 다음과 같습니다.

import sys
sys.path.append(os.path.abspath('../'))

0

나는 당신의 예에서 shebang을 봅니다. bin 스크립트를 ./bin/foo.py대신 으로 실행 python ./bin/foo.py하는 경우 shebang을 사용하여 $PYTHONPATH변수 를 변경하는 옵션이 있습니다 .

그러나 shebangs에서 직접 환경 변수를 변경할 수 없으므로 작은 도우미 스크립트가 필요합니다. 이 넣어 python.sh당신에 bin폴더 :

#!/usr/bin/env bash
export PYTHONPATH=$PWD/lib
exec "/usr/bin/python" "$@"

그리고 당신의 오두막을 변경할 ./bin/foo.py수#!bin/python.sh


0

터미널의 경로로 파이썬 파일을 실행하려고 할 때.

import sys
#For file name
file_name=sys.argv[0]
#For first argument
dir= sys.argv[1]
print("File Name: {}, argument dir: {}".format(file_name, dir)

파일 (test.py)을 저장합니다.

실행 시스템.

터미널을 열고 파일을 저장하는 디렉토리로 이동하십시오. 다음 쓰기

python test.py "/home/saiful/Desktop/bird.jpg"

Enter를 누르십시오.

산출:

File Name: test, Argument dir: /home/saiful/Desktop/bird.jpg

0

나는 사용한다:

from site import addsitedir

그런 다음 모든 상대 디렉토리를 사용할 수 있습니다! addsitedir('..\lib') ; 두 개의 점은 한 디렉토리를 먼저 이동 (위로) 함을 의미합니다.

모든 것이 현재 작업 디렉토리에서 시작하는 것에 달려 있음을 기억하십시오. C : \ Joe \ Jen \ Becky이면 addsitedir ( '.. \ lib')이 경로 C : \ Joe \ Jen \ lib로 가져옵니다.

C:\
  |__Joe
      |_ Jen
      |     |_ Becky
      |_ lib

응답에 감사하지만 현재 실행중인 스크립트에 상대적인 경로를 추가하지는 않습니다. 현재 작업 디렉토리에 상대적인 경로를 추가합니다
— James Harr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.