Python 3에서 execfile의 대안은 무엇입니까?


352

파이썬 3에서는 스크립트를 제거하여 스크립트를 빠르게로드하는 쉬운 방법을 모두 취소 한 것으로 보입니다. execfile()

내가 놓친 명백한 대안이 있습니까?


1
reload로 돌아 imp.reload3.2 이후.
Dougal

18
대화식으로 Python을 사용하는 경우 IPython 사용을 고려하십시오 %run script_name. 모든 버전의 Python에서 작동합니다.
Michael

1
3.4 impimportlib (반드시 가져와야 함) importlib.reload(mod_name)가져 오기 및 실행 mod_name합니다.
P. Wormer

3
runfile ( "filename.py")의 문제점은 무엇입니까?
mousomer

1
감사합니다 @ mousomer !! 호출 네임 스페이스 runfile()에서 실행하는 대신 자체 네임 스페이스에서 실행되는 Python 스크립트를 실행해야했기 때문에 기능을 정확하게 찾고있었습니다 . 내 응용 프로그램 : 속성을 사용하여 호출 된 스크립트의 디렉토리를 시스템 경로 ( )에 추가하십시오 : Python 3 ( ) 에서 사용 하거나 이에 상응하는 경우 포함 된 스크립트가 호출 네임 스페이스에서 실행되므로 호출 파일 이름으로 해석됩니다 . sys.path__file__execfile()exec(open('file.py').read())__file__
mastropi

답변:


389

설명서에 따르면 대신

execfile("./filename") 

사용하다

exec(open("./filename").read())

보다:


54
그들이 왜 그런 짓을했는지 아십니까? 이것은 이전보다 훨씬 더 장황합니다. 또한 Python3.3에서는 작동하지 않습니다. exec (open ( './ some_file'). read ())를 실행하면 "이러한 파일이나 디렉토리가 없습니다"라는 메시지가 나타납니다. '.py'확장자를 포함시키고 './'도 제외하려고 시도했습니다.
JoeyC

25
덜 간단하게, 이것은 execfile ()처럼 예외가 발생할 때 줄 번호를 제공하지 않습니다.
KDN

35
close그 파일 핸들도 필요합니다 . 파이썬 2의 변화를 싫어하는 또 다른 이유
Rebs

3
@Rebs이 예제에서 파일 핸들을 닫을 필요는 없습니다. 자동으로 (적어도 정규 CPython에서)
tiho

4
CPython 객체의 @Rebs는 참조 횟수가 0이 되 자마자 가비지 수집됩니다. 순환 참조 만이 지연 될 수 있습니다 ( stackoverflow.com/questions/9449489/… ). 이 경우 read ()가 반환 된 직후에 발생해야합니다. 그리고 파일 객체는 삭제 될 때 닫힙니다 (NB :이 링크는 명시 적으로 "항상 파일을 닫습니다"라고 명시되어 있습니다. 일반적으로 따르는 것이 좋습니다)
tiho

219

파일을 읽고 코드를 직접 실행해야합니다. 2to3 전류 대체

execfile("somefile.py", global_vars, local_vars)

같이

with open("somefile.py") as f:
    code = compile(f.read(), "somefile.py", 'exec')
    exec(code, global_vars, local_vars)

(컴파일 호출은 꼭 필요한 것은 아니지만 파일 이름을 코드 객체와 연결하여 디버깅을 좀 더 쉽게 만듭니다.)

보다:


3
이것은 나를 위해 작동합니다. 그러나 로컬 및 전역 인수를 잘못된 순서로 작성했습니다. 실제로는 exec (object [, globals [, locals]])입니다. 물론 당신이 주장을 원본으로 뒤집어 놓았다면, 2to3는 당신이 말한 것을 정확하게 만들 것입니다. :)
Nathan Shively-Sanders

3
global_vars 및 local_vars를 생략 할 수있는 경우 여기서 python3 대체는 python2에서도 작동합니다. execpython2의 문장 이지만 파렌 exec(code)이 무시되기 때문에 작동합니다.
medmunds

2
컴파일 사용시 +1 내가 "somefile.py"포함 inspect.getsourcefile(lambda _: None)때문에 컴파일하지 않고 실패 된 inspect코드에서오고 어디 모듈은 확인할 수 없습니다.
ArtOfWarfare

16
그건 .. 정말 못 생겼어 왜 3.x에서 execfile ()을 제거했는지 알고 있습니까? execfile을 사용하면 명령 줄 인수를 쉽게 전달할 수 있습니다.
초에 일화

3
open("somefile.py")somefile.py와 다른 문자 인코딩을 사용하는 경우 올바르지 않을 수 있습니다 locale.getpreferredencoding(). tokenize.open()대신 사용할 수 있습니다.
jfs

73

exec(open("filename").read())대한 대안으로 제공되는 경우가 많지만 지원되는 execfile("filename")중요한 세부 정보가 누락되었습니다 execfile.

Python3.x에 대한 다음 함수는 파일을 직접 실행하는 것과 동일한 동작을 수행 할 수있을만큼 가깝습니다. 그것은 running과 일치합니다 python /path/to/somefile.py.

def execfile(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
    globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), globals, locals)

# execute the file
execfile("/path/to/somefile.py")

노트:

  • 인코딩 문제를 피하기 위해 이진 판독 사용
  • 파일을 닫을 수 있습니다 (Python3.x는 이것에 대해 경고합니다)
  • __main__일부 스크립트는 예를 들어 모듈로로드되는지 여부를 확인하기 위해 이것에 의존 합니다 .if __name__ == "__main__"
  • __file__예외 메시지에 대한 설정 이 더 좋으며 일부 스크립트 __file__는 다른 파일의 경로를 가져 오는 데 사용 합니다.
  • 선택적 전역 및 지역 인수를 가져 와서 그대로 수정하여 execfile실행 후 변수를 다시 읽어서 정의 된 모든 변수에 액세스 할 수 있습니다.

  • Python2와 달리 현재 네임 스페이스는 기본적으로 수정 execfile되지 않습니다 . 이를 위해서는 globals()& 를 명시 적으로 전달해야합니다 locals().


68

최근 python-dev 메일 링리스트 에서 제안한 것처럼 runpy 모듈은 실행 가능한 대안 일 수 있습니다. 그 메시지에서 인용 :

https://docs.python.org/3/library/runpy.html#runpy.run_path

import runpy
file_globals = runpy.run_path("file.py")

다음과 같은 미묘한 차이점이 있습니다 execfile.

  • run_path항상 새로운 네임 스페이스를 만듭니다. 코드를 모듈로 실행하므로 전역과 지역간에 차이가 없으므로 init_globals인수가있는 것입니다. 글로벌이 반환됩니다.

    execfile현재 네임 스페이스 또는 지정된 네임 스페이스에서 실행됩니다. 주어진 경우 locals와 의 의미 globals는 클래스 정의 내부의 지역 및 전역과 유사합니다.

  • run_path 파일뿐만 아니라 계란과 디렉토리도 실행할 수 있습니다 (자세한 내용은 설명서를 참조하십시오).


1
어떤 이유로, 화면에 인쇄하도록 요청되지 않은 많은 정보를 출력합니다 ( Anaconda Python 3의 ' builtins '등). print ()로 출력 한 정보 만 시각화되도록 이것을 끄는 방법이 있습니까?
John Donn

현재 작업 공간에서 모든 변수를 저장하는 대신 모든 변수를 가져올 수 file_globals있습니까? 이렇게하면 file_globals['...']모든 변수에 대해 입력해야 합니다.
Adriaan

1
또한, 실행 된 코드로 정의 된 함수 및 클래스는 런피 함수가 반환 된 후에 올바르게 작동하지 않을 수 있습니다. 유스 케이스에 따라 주목할만한 가치
nodakai

@Adriaan "globals (). update (file_globals)"를 실행하십시오. 개인적으로 현재 작업 공간을 업데이트하기로 결정하기 전에 오류를 잡을 수 있기 때문에이 솔루션을 가장 좋아합니다.
Ron Kaminsky

@nodakai 정보 주셔서 감사합니다, 나는 그것을 그리워했다. 아직 그런 문제가 없었습니다. 무엇을 시작할지 궁금합니다.
Ron Kaminsky

21

이 방법은 호출자로부터 글로벌 및 로컬을 가져 오기 때문에 더 좋습니다.

import sys
def execfile(filename, globals=None, locals=None):
    if globals is None:
        globals = sys._getframe(1).f_globals
    if locals is None:
        locals = sys._getframe(1).f_locals
    with open(filename, "r") as fh:
        exec(fh.read()+"\n", globals, locals)

실제로, 이것은 py2에 더 가깝습니다 execfile. 위에 게시 된 다른 솔루션이 실패한 pytest를 사용할 때도 효과가있었습니다. 고마워! :)
Boriel

17

당신은 당신의 자신의 함수를 작성할 수 있습니다 :

def xfile(afile, globalz=None, localz=None):
    with open(afile, "r") as fh:
        exec(fh.read(), globalz, localz)

정말로 필요하다면 ...


1
-1 : exec 명령이이 방식으로 작동하지 않습니다. 코드는 어떤 버전의 파이썬에서도 실행되지 않습니다.
nosklo

6
-1 : 기본 파라미터 값은 모두 만드는 함수 정의시 평가 globalslocals의 정의에 포함 된 모듈 FO 글로벌 네임 스페이스 포인트 execfile()호출자의 글로벌 및 로컬 공간에 대신한다. 올바른 접근 방식은 None기본값 으로 사용 하고 inspect모듈 의 내부 검사 기능을 통해 발신자의 전역 및 지역을 결정하는 것 입니다.
Sven Marnach

12

로드하려는 스크립트가 실행하는 스크립트와 동일한 디렉토리에 있으면 "import"가 작업을 수행합니까?

코드를 동적으로 가져와야하는 경우 내장 함수 __ import__ 와 모듈 imp 를 살펴볼 가치가 있습니다.

>>> import sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'

test.py :

def run():
        return "Hello world!"

Python 3.1 이상을 사용하는 경우 importlib 도 살펴 봐야 합니다.


이것은 저에게 정답이었습니다. 이 블로그는 importlib dev.to/0xcrypto/dynamic-importing-stuff-in-python--1805
Nick Brady

9

여기 내가 가진 것이 있습니다 ( file두 예제 모두에서 소스 코드로 파일 경로에 이미 할당되어 있습니다).

execfile(file)

여기 내가 대체 한 것이 있습니다.

exec(compile(open(file).read(), file, 'exec'))

내가 가장 좋아하는 부분 : 두 번째 버전은 Python 2와 3에서 모두 잘 작동하므로 버전 종속 논리를 추가 할 필요가 없습니다.


5

ascii 또는 utf-8이 아닌 PEP-263 인코딩 선언을 사용하는 경우 위 패턴이 실패합니다. 데이터의 인코딩을 찾아 exec ()로 전달하기 전에 데이터를 올바르게 인코딩해야합니다.

class python3Execfile(object):
    def _get_file_encoding(self, filename):
        with open(filename, 'rb') as fp:
            try:
                return tokenize.detect_encoding(fp.readline)[0]
            except SyntaxError:
                return "utf-8"

    def my_execfile(filename):
        globals['__file__'] = filename
        with open(filename, 'r', encoding=self._get_file_encoding(filename)) as fp:
            contents = fp.read()
        if not contents.endswith("\n"):
            # http://bugs.python.org/issue10204
            contents += "\n"
        exec(contents, globals, globals)

3
"위의 패턴"은 무엇입니까? StackOverflow에서 다른 게시물을 참조 할 때 링크를 사용하십시오. "위의"와 같은 상대적인 포지셔닝 용어는 작동하지 않습니다. 답변을 투표, 날짜 또는 활동별로 분류하는 3 가지 방법이 있으며 가장 일반적인 답변 (투표 별)은 변동 적입니다. 시간이 지남에 따라 게시물과 주변 게시물의 점수가 다를 수 있으므로 다시 정렬되므로 비교가 덜 유용합니다.
ArtOfWarfare

아주 좋은 지적입니다. 그리고 거의 6 개월 전이 대답 내가 쓴 것을 주어, 나는 의미 "패턴 위의"에 의해 가정 stackoverflow.com/a/2849077/165082 (불행하게도 당신이 결의에 클릭해야), 또는 더 나은 아직 노암의 대답 :
에릭

2
일반적으로 답변에서 동일한 질문에 대한 다른 답변을 참조하려면 "Noam 's Answer"(예 :)를 입력하고 텍스트가 내가 언급 한 답변과 연결되지 않은 경우를 대비하여 텍스트를 연결합니다. 사용자는 자신의 계정 이름을 변경하거나 게시물을 너무 많이 편집하여 공동 위키가되므로 향후 사용자는 IE입니다.
ArtOfWarfare

포스터의 답변 이름을 제외하고 게시물에 특정 "응답"에 대한 URL을 어떻게 얻습니까?
DevPlayer

소스를보고 ID를 얻으십시오. 예를 들어 질문은 stackoverflow.com/questions/436198/… 입니다. 나는 더 나은 방법을 찾고 있지만, 댓글 근처에 마우스를 올리면 아무것도 보이지 않습니다
Eric

4

또한 순수한 Python 솔루션은 아니지만 IPython을 사용하는 경우 (아마도), 다음을 수행 할 수 있습니다.

%run /path/to/filename.py

똑같이 쉽습니다.


1

나는 여기에 초보자 일뿐이므로 이것을 발견하면 순수한 행운 일 것입니다.

인터프리터 프롬프트 >>> 명령을 사용하여 스크립트를 실행 한 후

    execfile('filename.py')

"NameError : name 'execfile'is not defined"에 대해 매우 기본적인 것을 시도했습니다.

    import filename

그것은 잘 작동했습니다 :-)

나는 이것이 도움이되기를 바랍니다. 훌륭한 힌트, 예제 및 새로 등장한 사람들에게 큰 영감을주는 모든 코드 주석에 대해 감사합니다!

우분투 16.014 LTS x64를 사용합니다. Python 3.5.2 (디폴트, 2016 년 11 월 17 일 17:05:23) [GCC 5.4.0 20160609] Linux


0

나에게 가장 깨끗한 방법은 importlib파일을 경로별로 모듈로 사용 하고 가져 오는 것입니다.

from importlib import util

def load_file(name, path):
    spec = util.spec_from_file_location(name, path)
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

사용 예

파일을 보자 foo.py.

print('i got imported')
def hello():
    print('hello from foo')

이제 일반 모듈처럼 가져 와서 사용하십시오.

>>> foo = load_file('foo', './foo.py')
i got imported
>>> foo.hello()
hello from foo

exec(open(...))네임 스페이스를 어수선하게 만들거나 불필요하게 엉망이되지 않기 때문에 직접 접근 방식 보다이 기술을 선호합니다 $PATH.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.