Python 3では、execfile()
を削除することでスクリプトを素早くロードするためのすべての簡単な方法がキャンセルされたようです。
私が見逃している明白な代替手段はありますか?
あなたはただファイルを読んで自分でコードを実行することになっています。 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)
(コンパイル呼び出しは厳密には必要ありませんが、ファイル名とコードオブジェクトを関連付けることで、デバッグが少し簡単になります。)
見る:
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")
注:
__main__
を定義します。いくつかのスクリプトはこれらがモジュールとしてロードされているかどうかをチェックするためにこれに依存します。 if __== "__main__"
__file__
を設定することは例外メッセージのためにより良く、そしていくつかのスクリプトはそれらに関連する他のファイルのパスを得るために__file__
を使います。オプションのglobalsとlocals引数を取り、それらをexecfile
のようにインプレースで修正します - そのため、実行後に変数を読み返すことによって定義された任意の変数にアクセスできます。
Python2のexecfile
とは異なり、これはデフォルトでnotを変更します。そのためにはglobals()
とlocals()
を明示的に渡す必要があります。
最近 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
はファイルを実行できるだけでなく、eggとディレクトリも実行できます(詳細についてはそのドキュメントを参照してください)。
あなたはあなた自身の関数を書くことができます:
def xfile(afile, globalz=None, localz=None):
with open(afile, "r") as fh:
exec(fh.read(), globalz, localz)
あなたが本当に必要な場合は...
これは、呼び出し側からグローバルとローカルを取得するため、優れています。
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)
あなたがロードしたいスクリプトがあなたが実行するものと同じディレクトリにあるならば、多分「インポート」は仕事をするでしょうか?
動的にコードをインポートする必要があるなら、組み込み関数 _ 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 も見てください。
これは私が持っていたものです(両方の例でfile
はソースコードでファイルへのパスに既に割り当てられています):
execfile(file)
これは私がそれを置き換えたものです:
exec(compile(open(file).read(), file, 'exec'))
私のお気に入りの部分:2番目のバージョンはPython 2と3の両方で問題なく動作します。つまり、バージョン依存ロジックを追加する必要はありません。
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)
また、純粋なPythonソリューションではありませんが、IPythonを使用している場合は(とにかくおそらく)、次のようにすることができます。
%run /path/to/filename.py
どちらも同じくらい簡単です。
私はここでは初心者なので、もしこれを見つけたら多分それは純粋な運です。
インタプリタのプロンプト>>>でスクリプトを実行しようとした後
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]