web-dev-qa-db-ja.com

Python 3のexecfileに代わるものは何ですか?

Python 3では、execfile()を削除することでスクリプトを素早くロードするためのすべての簡単な方法がキャンセルされたようです。

私が見逃している明白な代替手段はありますか?

302
R S

ドキュメントによると の代わりに

execfile("./filename") 

つかいます

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

見る:

329
Pedro Vagner

あなたはただファイルを読んで自分でコードを実行することになっています。 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)

(コンパイル呼び出しは厳密には必要ありませんが、ファイル名とコードオブジェクトを関連付けることで、デバッグが少し簡単になります。)

見る:

201

exec(open("filename").read())はしばしばexecfile("filename")の代替として与えられますが、それはexecfileがサポートしていた重要な詳細を見逃しています。

次のPython3.x用の関数は、ファイルを直接実行するのと同じ振る舞いをすることができるようにできる限り近いです。これは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 __== "__main__"
  • __file__を設定することは例外メッセージのためにより良く、そしていくつかのスクリプトはそれらに関連する他のファイルのパスを得るために__file__を使います。
  • オプションのglobalsとlocals引数を取り、それらをexecfileのようにインプレースで修正します - そのため、実行後に変数を読み返すことによって定義された任意の変数にアクセスできます。

  • Python2のexecfileとは異なり、これはデフォルトでnotを変更します。そのためにはglobals()locals()を明示的に渡す必要があります。

56
ideasman42

最近 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引数のみがある理由です)。グローバルが返されます。

    現在のネームスペースまたは指定されたネームスペースで実行されたexecfilelocalsglobalsのセマンティクスは、与えられた場合、クラス定義内のローカルとグローバルに似ていました。

  • run_pathはファイルを実行できるだけでなく、eggとディレクトリも実行できます(詳細についてはそのドキュメントを参照してください)。

52
Jonas Schäfer

あなたはあなた自身の関数を書くことができます:

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

あなたが本当に必要な場合は...

18
Evan Fosmark

これは、呼び出し側からグローバルとローカルを取得するため、優れています。

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)
18
Noam

あなたがロードしたいスクリプトがあなたが実行するものと同じディレクトリにあるならば、多分「インポート」は仕事をするでしょうか?

動的にコードをインポートする必要があるなら、組み込み関数 _ 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 も見てください。

11
ascobol

これは私が持っていたものです(両方の例でfileはソースコードでファイルへのパスに既に割り当てられています):

execfile(file)

これは私がそれを置き換えたものです:

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

私のお気に入りの部分:2番目のバージョンはPython 2と3の両方で問題なく動作します。つまり、バージョン依存ロジックを追加する必要はありません。

8
ArtOfWarfare

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)
5
Eric

また、純粋なPythonソリューションではありませんが、IPythonを使用している場合は(とにかくおそらく)、次のようにすることができます。

%run /path/to/filename.py

どちらも同じくらい簡単です。

3
R S

私はここでは初心者なので、もしこれを見つけたら多分それは純粋な運です。

インタプリタのプロンプト>>>でスクリプトを実行しようとした後

    execfile('filename.py')

「NameError:name 'execfile'は定義されていません」というエラーが発生したため、非常に基本的な方法を試してみました。

    import filename

うまくいった:-)

これが参考になることを願っていますし、素晴らしいヒント、例、そして初心者からコメントされた、初心者向けのすばらしいコードをありがとうございます。

Ubuntu 16.014 LTS x 64を使用しています。 Python 3.5.2(デフォルト、2016年11月17日、17:05:23)[GCC 5.4.0 20160609] [Linux]

1
Claude