파이썬에서 현재 실행중인 파일의 경로를 얻으려면 어떻게해야합니까?


193

이것은 초보자 질문처럼 보이지만 그렇지 않습니다. 일부 공통 접근 방식은 모든 경우에 작동하지 않습니다.

sys.argv [0]

이것은을 사용하는 것을 의미 path = os.path.abspath(os.path.dirname(sys.argv[0]))하지만 다른 디렉토리의 다른 Python 스크립트에서 실행하는 경우 작동하지 않으며 실제로 발생할 수 있습니다.

__파일__

이것은을 사용하는 것을 의미 path = os.path.abspath(os.path.dirname(__file__))하지만 이것이 작동하지 않는다는 것을 알았습니다.

  • py2exe이없는 __file__속성을하지만,이 해결 방법은
  • 속성 execute()이없는 IDLE에서 실행할 때__file__
  • 내가 얻는 OS X 10.6 NameError: global name '__file__' is not defined

불완전한 답변이 포함 된 관련 질문 :

위의 모든 유스 케이스에서 작동 하는 일반적인 솔루션을 찾고 있습니다.

최신 정보

테스트 케이스의 결과는 다음과 같습니다.

파이썬 a.py의 출력 (Windows)

a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz

b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz

a.py

#! /usr/bin/env python
import os, sys

print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print

execfile("subdir/b.py")

하위 디렉토리 /b.py

#! /usr/bin/env python
import os, sys

print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print

나무

C:.
|   a.py
\---subdir
        b.py

답변:


80

실행중인 기본 스크립트의 위치를 ​​직접 결정할 수 없습니다. 결국, 때로는 스크립트가 파일에서 전혀 나오지 않았습니다. 예를 들어, 대화식 인터프리터 또는 메모리에만 저장된 동적으로 생성 된 코드에서 가져올 수 있습니다.

그러나 모듈은 항상 파일에서로드되므로 모듈의 위치를 ​​안정적으로 결정할 수 있습니다. 다음 코드를 사용하여 모듈을 작성하고 기본 스크립트와 동일한 디렉토리에 넣으면 기본 스크립트가 모듈을 가져 와서 해당 모듈을 찾을 수 있습니다.

some_path / module_locator.py :

def we_are_frozen():
    # All of the modules are built-in to the interpreter, e.g., by py2exe
    return hasattr(sys, "frozen")

def module_path():
    encoding = sys.getfilesystemencoding()
    if we_are_frozen():
        return os.path.dirname(unicode(sys.executable, encoding))
    return os.path.dirname(unicode(__file__, encoding))

some_path / main.py :

import module_locator
my_path = module_locator.module_path()

다른 디렉토리에 여러 개의 기본 스크립트가있는 경우 둘 이상의 module_locator 사본이 필요할 수 있습니다.

물론 메인 스크립트가 스크립트와 같은 위치에있는 모듈을 가져올 수없는 다른 도구로로드 된 경우 운이 좋지 않습니다. 그런 경우에, 당신이 추구하는 정보는 단순히 프로그램의 어느 곳에도 존재하지 않습니다. 가장 좋은 방법은 도구 작성자에게 버그를 신고하는 것입니다.


2
나는 OS 10.6에서 내가 얻을 언급 NameError: global name '__file__' is not defined사용하여 파일을 이이 IDLE 내부 없습니다. __file__모듈 내부에만 정의되어 있다고 생각하십시오 .
sorin

1
@ Sorin Sbarnea : 나는 그 문제를 해결하는 방법으로 대답을 업데이트했습니다.
Daniel Stutzbach

2
고맙지 만 사실 누락 문제 __file__는 유니 코드와 관련이 없습니다. 왜 __file__정의 되지 않았는지 모르겠지만 일반적인 솔루션을 찾고 있는데 이것이 모든 경우에 효과적입니다.
sorin

1
모든 경우에 가능하지는 않습니다. 예를 들어 나는 wscript 파일 (python) 내부의 waf.googlecode.com 에서이 작업을 시도합니다. 이러한 파일은 실행되지만 모듈은 아니며 모듈로 만들 수 없습니다 (소스 트리의 하위 디렉토리 일 수 있음).
sorin

1
some_path/module_locator.py대신 위치를 제공 하지 않습니까?
Casebash

68

먼저 inspect및 에서 가져와야합니다.os

from inspect import getsourcefile
from os.path import abspath

다음으로, 당신이 사용하는 소스 파일을 찾으려면 어디든지

abspath(getsourcefile(lambda:0))

가장 좋은 답변입니다. 감사합니다.
Devan Williams

4
좋은 대답입니다. 감사. 또한 (가장 다른 OS에서 실행되는) 가장 짧고 휴대하기 쉬운 것처럼 보이며 NameError: global name '__file__' is not defined(다른 솔루션으로 인해) 다른 문제가 발생하지 않습니다 .
Edward

똑같이 짧은 또 다른 가능성 : lambda:_. 그것은 나를 위해 일했습니다-그것이 항상 효과가 있는지 확실하지 않습니다. lambda:0아마 빠른 일부 헤아릴 수 없을 정도로 소량으로 실행 (또는 어쩌면 이렇게 작은하지 ... A는 부하 즉시 또는 더 빨리 뭔가 수 있습니다 0부하 글로벌 대 _논쟁의 여지가의 청소기 또는 쉽게 읽거나 더 영리 여부 / 모호?).
ArtOfWarfare

내가 시도한 거의 모든 제안과 마찬가지로, 이것은 내가 실행중인 디렉토리 파일이 아닌 cwd를 반환합니다 (디버깅).
James

1
@James-이 코드는 실행중인 파일에 들어갑니다 ... 실행 getsourcefile(lambda:0)은 의미가 없으며 None대화 형 프롬프트에서 실행하려고하면 반환 됩니다 ( lambda소스 파일에 없기 때문에). 대화 형 환경에서 다른 기능이나 객체가 나오는 곳 abspath(getsourcefile(thatFunctionOrObject))이 더 도움이 될 수 있습니까?
ArtOfWarfare

16

이 솔루션은 실행 파일에서도 강력합니다.

import inspect, os.path

filename = inspect.getframeinfo(inspect.currentframe()).filename
path     = os.path.dirname(os.path.abspath(filename))

2
이것이 정답이어야합니다. 이것은 에서조차 작동 entry_point: console_script하지만 다른 답변은 없습니다.
Polv

15

비슷한 문제가 발생하여 문제를 해결할 수 있다고 생각합니다.

def module_path(local_function):
   ''' returns the module path without the use of __file__.  Requires a function defined
   locally in the module.
   from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
   return os.path.abspath(inspect.getsourcefile(local_function))

일반 스크립트 및 유휴 상태에서 작동합니다. 내가 말할 수있는 것은 다른 사람들을 위해 시험해 보는 것입니다!

내 일반적인 사용법 :

from toolbox import module_path
def main():
   pass # Do stuff

global __modpath__
__modpath__ = module_path(main)

이제 __file__ 대신 __modpath__를 사용합니다.


2
PEP8 코딩 스타일 가이드 에 따르면 이중 선행 및 후행 밑줄로 이름을 작성해서는 안되므로 이름을 __modpath__바꿔야합니다. 또한 global성명서 가 필요하지 않을 수도 있습니다 . 그렇지 않으면 +1!
martineau 2016 년

4
실제로에 대한 호출에서 바로 로컬 함수를 정의 할 수 있습니다 module_path(). 즉 module_path(lambda _: None), 스크립트의 다른 내용에 의존하지 않습니다.
martineau

@martineau : 나는 당신의 제안을 lambda _: None받아 거의 2 년 동안 사용해 왔지만, 지금은 그것을 단지 응축 할 수 있다는 것을 알게되었습니다 lambda:0. _인수를 전혀 사용하지 않고의 무시 된 인수를 사용하여 양식을 제안한 특별한 이유가 있습니까? None접두사가 아닌 공백으로 시작되는 것보다 우수한 것이 0있습니까? 둘 다 똑같이 암호입니다. 한 문자는 8 자이고 다른 문자는 14 자입니다.
ArtOfWarfare

@ArtOfWarfare :이 둘의 차이점 lambda _:은 하나의 인수를 취하는 함수이고 lambda:어떤 것도받지 않는 함수입니다 . 함수가 호출되지 않기 때문에 중요하지 않습니다. 마찬가지로 어떤 반환 값이 사용되는지는 중요하지 않습니다. 나는 None그것이 아무것도하지 않았고 결코 호출 할 수없는 기능이라는 것을 나타내는 것처럼 보였기 때문에 선택 했다고 생각합니다. 그 앞의 공간은 선택 사항이며 가독성 향상을 위해서만 있습니다 (항상 PEP8을 따르려고 시도하는 것은 습관을 형성합니다).
martineau

@ martineau : 그것은 lambda결코 의도하지 않은 무언가를 위해 그것을 사용하는 것은 분명히 남용입니다 . PEP8을 따라야한다면 올바른 내용은 pass아닌 것 None같지만,에 문장을 넣는 것은 유효하지 않으므로 lambda값이있는 무언가를 넣어야합니다. 이 당신이에 넣어 수있는 몇 가지 유효한 2 문자 것들,하지만 난 당신이 넣어 수있는 유일한 유효한 단일 문자 일들이 0-9 생각 (또는 외부에 할당 된 단일 문자 변수 이름 lambda.) 나는 그림 0최고 0-의 무 (無)를 나타냅니다 9.
ArtOfWarfare

6

짧은 대답은 원하는 정보를 얻을 수있는 보장 된 방법이 없지만 거의 항상 실제로 작동하는 휴리스틱이 있다는 것입니다. 당신이 볼 수 어떻게 C에서 실행 파일의 위치를 찾을 수 있습니까? . C 관점에서 문제에 대해 설명하지만 제안 된 솔루션은 Python으로 쉽게 기록됩니다.


지금 메타에 대한 논의를 시작했습니다 그래서 안녕하세요, 제 플래그가 거부되었습니다 : meta.stackoverflow.com/questions/277272/...은
ArtOfWarfare

그러나이 페이지에는 이미 간단한 작업 답변이 있습니다. 내 솔루션은 잘 작동합니다 : stackoverflow.com/a/33531619/3787376 .
Edward

5

내 답변 에서 신뢰할 수없는 변수를 사용하지 않는 이유를 비롯하여 관련 정보 는 상위 폴더에서 모듈 가져 오기 질문에 대한 답변을 참조하십시오 __file__. 이 간단한 솔루션은 모듈 os과 같은 다른 운영 체제와 호환되며 inspectPython의 일부로 제공됩니다.

먼저 inspectos 모듈의 일부를 가져와야 합니다.

from inspect import getsourcefile
from os.path import abspath

다음으로 파이썬 코드에서 필요한 다른 곳에서 다음 줄을 사용하십시오.

abspath(getsourcefile(lambda:0))

작동 방식 :

내장 모듈 os(아래 설명)에서 abspath도구를 가져 옵니다 .

사용중인 시스템에 따라 Mac, NT 또는 Posix 용 OS 루틴.

그런 다음 getsourcefile내장 모듈에서 (아래 설명)을 가져옵니다 inspect.

라이브 Python 객체에서 유용한 정보를 얻습니다.

  • abspath(path) 파일 경로의 절대 / 풀 버전을 반환합니다
  • getsourcefile(lambda:0)어떻게 든 람다 함수 객체의 내부 소스 파일을 얻으므로 '<pyshell#nn>'Python 셸에서 반환하거나 현재 실행중인 Python 코드의 파일 경로를 반환합니다.

abspath결과를 사용하여 getsourcefile(lambda:0)생성 된 파일 경로가 Python 파일의 전체 파일 경로인지 확인해야합니다.
이 설명 솔루션은 원래 Python에서 현재 실행중인 파일의 경로를 얻는 방법에 대한 답변의 코드를 기반으로 설명되었습니다 . .


그래, 난 그냥 같은 해결책을 생각해
냈는데

5

당신은 단순히 전화했다 :

path = os.path.abspath(os.path.dirname(sys.argv[0]))

대신에:

path = os.path.dirname(os.path.abspath(sys.argv[0]))

abspath()sys.argv[0](코드가있는 파일 이름) 의 절대 경로를 제공 하고 파일 이름 dirname()없이 디렉토리 경로를 반환합니다.


4

이것은 인터프리터 등을 사용하지 않는 한 크로스 플랫폼 방식으로 트릭을 수행해야합니다.

import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))

sys.path[0]호출 스크립트가있는 디렉토리입니다 (해당 스크립트에서 사용할 모듈을 찾는 첫 번째 위치). 우리는 파일 자체의 이름을 끝낼 수 있습니다 sys.argv[0](이것은 내가 한 것입니다 os.path.basename). os.path.join크로스 플랫폼 방식으로 연결합니다. os.path.realpath스크립트 자체와 다른 이름을 가진 심볼릭 링크가 있는지 확인하여 스크립트의 실제 이름을 얻습니다.

나는 Mac이 없습니다. 그래서 나는 이것을 테스트하지 않았습니다. 제대로 작동하는지 알려주십시오. 파이썬 3.4를 사용하여 Linux (Xubuntu)에서 이것을 테스트했습니다. 이 문제에 대한 많은 솔루션이 Mac에서 작동하지 않습니다 (Mac __file__에는 존재하지 않는다고 들었 으므로).

스크립트가 심볼릭 링크 인 경우 링크 된 파일의 경로 (심볼릭 링크의 경로가 아님)를 제공합니다.


2

모듈 Path에서 사용할 수 있습니다 pathlib:

from pathlib import Path

# ...

Path(__file__)

call to parent를 사용 하여 경로를 더 진행할 수 있습니다 .

Path(__file__).parent

이 답변은 StackOverflow 사용자가 자주 언급했듯이 신뢰할__file__없는 변수를 사용합니다 (항상 전체 파일 경로는 아니며 모든 운영 체제에서 작동하지는 않습니다). 대답을 포함하지 않도록 변경하면 문제가 줄어들고 상호 호환성이 향상됩니다. 자세한 내용은 stackoverflow.com/a/33532002/3787376을 참조하십시오 .
Edward

@ mrroot5 좋아요, 코멘트를 삭제하십시오.
Gavriel Cohen

1

코드가 파일에서 오는 경우 전체 이름을 얻을 수 있습니다

sys._getframe().f_code.co_filename

함수 이름을 다음과 같이 검색 할 수도 있습니다. f_code.co_name


0

간단히 다음을 추가하십시오.

from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)

또는:

from sys import *
print(sys.argv[0])

0

내 해결책은 다음과 같습니다.

import os
print(os.path.dirname(os.path.abspath(__file__)))

-1
import os
current_file_path=os.path.dirname(os.path.realpath('__file__'))

이것은 말이되지 않습니다. 첫째, '__file__'문자열이 아니어야합니다. 둘째, 수행 한 경우이 __file__코드 행이있는 파일에서만 작동하고 실행되는 파일에서는 작동하지 않습니까?
Andreas Storvik Strauman 19 :
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.