web-dev-qa-db-ja.com

任意のpythonソースファイルをインポートします。(Python 3.3+)

Python 3.3で任意のpythonソースファイル(ファイル名に任意の文字を含めることができ、常に.pyで終わるとは限らない)をインポートするにはどうすればよいですか? +

imp.load_module を次のように使用しました。

>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
...     mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>

Python 3.3で動作しますが、imp.load_moduleのドキュメントによると、非推奨です:

非推奨。バージョン3.3以降:モジュールのロードにはローダーを使用する必要があり、find_module()は非推奨です。

およびimpモジュールのドキュメントでは、importlibの使用を推奨しています。

新しいプログラムでは、このモジュールではなくimportlibを使用する必要があります。

非推奨のimp.load_module関数を使用せずに、任意のpythonソースファイルをPython 3.3+で読み込む)の適切な方法は何ですか?

53
falsetru

importlibテストコード から解決策を見つけました。

importlib.machinery.SourceFileLoader :の使用

>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>

[〜#〜] note [〜#〜]Python 3.3 +でのみ動作します。

[〜#〜] update [〜#〜]Loader.load_module は、Python 3.4。 Loader.exec_module 代わりに:

>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>

>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
52
falsetru

@falsetruのソリューションの短いバージョン:

>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>

Python 3.5および3.6。

コメントによると、任意のファイル拡張子では機能しません。

17
Stefan Scherfke

@falsetruに似ていますが、Python 3.5 +および何を考慮に入れますか importlib docimportlib.util.module_from_spec over types.ModuleType

この関数[importlib.util.module_from_spec]は、types.ModuleTypeを使用して新しいモジュールを作成するよりも優先されます。これは、仕様を使用してモジュール上のインポート制御属性をできるだけ多く設定するためです。

importlib.machinery.SOURCE_SUFFIXESリストを変更することにより、importlibのみのファイルをインポートできます。

import importlib

importlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any file
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()
7
awalllllll