[python] 모듈 __file__ 속성은 절대적입니까 아니면 상대적입니까?

이해하는 데 문제가 __file__있습니다. 내가 이해 한 바에 __file__따르면 모듈이로드 된 절대 경로를 반환합니다.

나는 이것을 생산하는 데 문제가 있습니다 : 나는 return 에서 실행되는 abc.pywith one statement 가 있습니다. 반환 에서 실행 . 이유는 무엇입니까?print __file__/d/projects/ python abc.pyabc.py/d/projects/abc.py



답변

로부터 문서 :

__file__파일에서로드 된 경우 모듈이로드 된 파일의 경로 이름입니다. __file__인터프리터에 정적으로 링크 된 C 모듈 에는 속성이 없습니다. 공유 라이브러리에서 동적으로로드 된 확장 모듈의 경우 공유 라이브러리 파일의 경로 이름입니다.

보내는 사람 메일 링리스트 스레드 질문에 대한 코멘트에 @kindall로 연결 :

이 특정 예제를 재현하려고 시도하지는 않았지만 그 이유는 가져올 때마다 getpwd ()를 호출 할 필요가없고 현재 디렉터리를 캐시하기 위해 어떤 종류의 프로세스 내 변수를 갖고 싶지 않기 때문입니다. (getpwd ()는 상대적으로 느리고 때로는 완전히 실패 할 수 있으며 캐시를 시도하면 잘못 될 위험이 있습니다.)

대신 우리가하는 일은 sys.path의 요소를 살펴보고 절대 경로로 바꾸는 site.py의 코드입니다. 그러나이 코드는 ”가 sys.path 앞에 삽입되기 전에 실행되므로 sys.path의 초기 값은 ”입니다.

나머지 부분 sys.path에서는을 포함하지 않는 것이 ''좋습니다.

따라서 sys.path모듈을 포함하는 부분을 ​​벗어나면 절대 경로를 얻을 수 있습니다. sys.path모듈을 포함 하는 부분 안에 있다면 상대 경로를 얻을 수 있습니다.

현재 디렉토리에 모듈을로드하고, 현재 디렉토리가있는 경우 하지sys.path, 당신은 절대 경로를 얻을 수 있습니다.

현재 디렉토리에 모듈을로드하고 현재 디렉토리 sys.path있는 경우 상대 경로를 얻을 수 있습니다.


답변

__file__상대 경로를 사용하여 스크립트를 직접 실행할 때를 제외하고 는 Python 3.4 이후 절대적입니다 .

모듈 __file__속성 (및 관련 값)은 이제 __main__.__file__스크립트가 상대 경로를 사용하여 직접 실행 된 경우를 제외하고는 기본적으로 항상 절대 경로를 포함해야 합니다. ( bpo-18416 에서 Brett Cannon에 의해 기고 .)

그래도 symlink를 해결하는지 확실하지 않습니다.

상대 경로 전달의 예 :

$ python script.py


답변

후기 간단한 예 :

from os import path, getcwd, chdir

def print_my_path():
    print('cwd:     {}'.format(getcwd()))
    print('__file__:{}'.format(__file__))
    print('abspath: {}'.format(path.abspath(__file__)))

print_my_path()

chdir('..')

print_my_path()

Python-2. *에서 두 번째 호출 path.abspath(__file__)은 현재 디렉터리를 기반으로 잘못 결정합니다 .

cwd:     C:\codes\py
__file__:cwd_mayhem.py
abspath: C:\codes\py\cwd_mayhem.py
cwd:     C:\codes
__file__:cwd_mayhem.py
abspath: C:\codes\cwd_mayhem.py

@techtonik에서 언급했듯이 Python 3.4 이상에서는 __file__절대 경로를 반환 하므로 제대로 작동합니다 .


답변

@kindall에서 제공하는 Guido 메일의 도움 sys.path으로이 조회의 결과로, 및 파일 의 각 구성원에서 모듈을 찾으려고 시도하는 표준 가져 오기 프로세스를 이해할 수 있습니다 (자세한 내용은 PyMOTW 모듈 및 가져 오기 참조 ). 따라서 모듈이 절대 경로에 sys.path있으면 결과는 절대이지만 상대 경로에 있으면 sys.path결과는 상대입니다.

이제 site.py시작 파일은 sys.path초기를 제외하고 에서 절대 경로 만 제공 ''하므로 PYTHONPATH (경로도 절대로 설정되고 접두사를 붙임 sys.path)를 설정하는 것 외에 다른 방법으로 변경하지 않으면 항상 절대 경로 를 얻을 수 있습니다. 경로이지만 모듈이 현재 디렉토리를 통해 액세스 될 때.

이제 sys.path를 재미있는 방법으로 속이면 무엇이든 얻을 수 있습니다.

예를 들어 당신은 샘플 모듈이있는 경우 foo.py/tmp/코드를 가진 :

import sys
print(sys.path)
print (__file__)

/ tmp에 들어가면 다음을 얻습니다.

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
./foo.py

에있을 때 /home/user추가하면 /tmp다음 PYTHONPATH을 얻을 수 있습니다.

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
/tmp/foo.py

를 추가해도 ../../tmp정규화되고 결과는 동일합니다.

그러나 PYTHONPATH직접 사용하는 대신 재미있는 경로를 사용하면 원인만큼 재미있는 결과를 얻을 수 있습니다.

>>> import sys
>>> sys.path.append('../../tmp')
>>> import foo
['', '/usr/lib/python3.3', .... , '../../tmp']
../../tmp/foo.py

Guido는 위에서 인용 한 스레드에서 파이썬이 절대 경로의 모든 항목을 변환하지 않는 이유를 설명합니다.

가져올 때마다 getpwd ()를 호출 할 필요는 없습니다 …. getpwd ()는 상대적으로 느리고 때로는 완전히 실패 할 수 있습니다.

따라서 경로는 그대로 사용 됩니다 .


답변