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처럼 라이브러리를 설치
    하거나
  • 설정 PYTHONPATHlib

또는 각 파일에 한 줄을 추가하려면 맨 위에 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.