フルパスを指定してPythonモジュールをロードするにはどうすればよいですか?
ファイルは構成オプションであるため、ファイルシステムのどこにでも配置できることに注意してください。
フルパスを指定してPythonモジュールをロードするにはどうすればよいですか?
ファイルは構成オプションであるため、ファイルシステムのどこにでも配置できることに注意してください。
Python 3.5 以降の場合:
import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
Python 3.3 および 3.4 の場合:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(ただし、これは Python 3.4 で廃止されました。)
Python 2 の場合:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
コンパイルされた Python ファイルと DLL には、同等の便利な関数があります。
http://bugs.python.org/issue21436も参照してください。
(imp を使用するよりも) sys.path にパスを追加する利点は、単一のパッケージから複数のモジュールをインポートするときに物事が単純化されることです。例えば:
import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')
from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch
最上位モジュールがファイルではなく、__init__.py を使用してディレクトリとしてパッケージ化されている場合、受け入れられているソリューションはほとんど機能しますが、完全ではありません。Python 3.5 以降では、次のコードが必要です (「sys.modules」で始まる行が追加されていることに注意してください)。
MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
import importlib
import sys
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
この行がないと、exec_module が実行されると、最上位の __init__.py の相対インポートを最上位のモジュール名 (この場合は "mymodule") にバインドしようとします。ただし、「mymodule」はまだロードされていないため、「SystemError: 親モジュール 'mymodule' がロードされていないため、相対インポートを実行できません」というエラーが発生します。そのため、ロードする前に名前をバインドする必要があります。この理由は、相対インポート システムの基本的な不変条件です。 )、後者は前者の foo 属性として表示される必要があります"ここで説明したように.
構成ファイルを特にインポートしたくないようです (これには、多くの副作用と追加の複雑さが伴います)。それを実行して、結果の名前空間にアクセスできるようにしたいだけです。標準ライブラリは、runpy.run_pathの形式で専用の API を提供します。
from runpy import run_path
settings = run_path("/path/to/file.py")
このインターフェイスは、Python 2.7 および Python 3.2+ で使用できます。
このようなことをして、構成ファイルが置かれているディレクトリをPythonロードパスに追加し、ファイルの名前(この場合は「config」)を事前に知っていると仮定して、通常のインポートを行うこともできます。
散らかっていますが、動作します。
configfile = '~/config.py'
import os
import sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config
ロードまたはインポートを意味しますか?
リストを操作sys.path
してモジュールへのパスを指定してから、モジュールをインポートできます。たとえば、次のモジュールがあるとします。
/foo/bar.py
あなたができること:
import sys
sys.path[0:0] = ['/foo'] # Puts the /foo directory at the start of your path
import bar
これは、2.7 から 3.5 までのすべての Python バージョン、およびおそらく他のバージョンでも機能するコードです。
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
私はそれをテストしました。見苦しいかもしれませんが、今のところすべてのバージョンで動作するのはこれだけです。
__import__
と を使用してこれを行うことができますchdir
。
def import_file(full_path_to_module):
try:
import os
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
save_cwd = os.getcwd()
os.chdir(module_dir)
module_obj = __import__(module_name)
module_obj.__file__ = full_path_to_module
globals()[module_name] = module_obj
os.chdir(save_cwd)
except Exception as e:
raise ImportError(e)
return module_obj
import_file('/home/somebody/somemodule.py')
imp.find_module()
と を使用しimp.load_module()
て、指定されたモジュールをロードできると思います。モジュール名をパスから分割する必要があります。つまり、ロードする場合は、次のように/home/mypath/mymodule.py
する必要があります。
imp.find_module('mymodule', '/home/mypath/')
...しかし、それは仕事を成し遂げるはずです。
pkgutil
モジュール (具体的にはメソッド) を使用walk_packages
して、現在のディレクトリ内のパッケージのリストを取得できます。そこから、importlib
機械を使用して必要なモジュールをインポートするのは簡単です。
import pkgutil
import importlib
packages = pkgutil.walk_packages(path='.')
for importer, name, is_package in packages:
mod = importlib.import_module(name)
# do whatever you want with module now, it's been imported!
Python 3.4 のこの領域は、理解するのが非常に難しいようです! しかし、Chris Calloway のコードを使って少しハッキングしたところ、何とか機能させることができました。基本機能はこちら。
def import_module_from_file(full_path_to_module):
"""
Import a module given the full path/filename of the .py file
Python 3.4
"""
module = None
try:
# Get module name and path from full path
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
# Get module "spec" from filename
spec = importlib.util.spec_from_file_location(module_name,full_path_to_module)
module = spec.loader.load_module()
except Exception as ec:
# Simple error printing
# Insert "sophisticated" stuff here
print(ec)
finally:
return module
これは、Python 3.4 の非推奨でないモジュールを使用しているようです。理由を理解しているふりはしませんが、プログラム内から機能するようです。Chris のソリューションはコマンド ラインでは機能しますが、プログラム内からは機能しないことがわかりました。
優れていると言っているわけではありませんが、完全を期すために、exec
Python 2 と Python 3 の両方で利用できる関数を提案したいと思います。
exec
辞書として提供されるグローバル スコープまたは内部スコープのいずれかで、任意のコードを実行できます。
たとえば"/path/to/module
、関数を使用して " に格納されたモジュールがある場合foo()
、次のようにして実行できます。
module = dict()
with open("/path/to/module") as f:
exec(f.read(), module)
module['foo']()
これにより、コードを動的にロードしていることがもう少し明確になり、カスタムのビルトインを提供する機能など、いくつかの追加機能が付与されます。
また、キーではなく属性を介してアクセスすることが重要な場合は、そのようなアクセスを提供するグローバル用のカスタム dict クラスを設計できます。
class MyModuleClass(dict):
def __getattr__(self, name):
return self.__getitem__(name)
を使ったパッケージを作りましたimp
。私はそれを呼び出しimport_file
、これが使用方法です:
>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
次の場所で入手できます。
http://pypi.python.org/pypi/import_file
または
実行時にパッケージモジュールをインポートする(Pythonレシピ)
http://code.activestate.com/recipes/223972/
###################
## #
## classloader.py #
## #
###################
import sys, types
def _get_mod(modulePath):
try:
aMod = sys.modules[modulePath]
if not isinstance(aMod, types.ModuleType):
raise KeyError
except KeyError:
# The last [''] is very important!
aMod = __import__(modulePath, globals(), locals(), [''])
sys.modules[modulePath] = aMod
return aMod
def _get_func(fullFuncName):
"""Retrieve a function object from a full dotted-package name."""
# Parse out the path, module, and function
lastDot = fullFuncName.rfind(u".")
funcName = fullFuncName[lastDot + 1:]
modPath = fullFuncName[:lastDot]
aMod = _get_mod(modPath)
aFunc = getattr(aMod, funcName)
# Assert that the function is a *callable* attribute.
assert callable(aFunc), u"%s is not callable." % fullFuncName
# Return a reference to the function itself,
# not the results of the function.
return aFunc
def _get_class(fullClassName, parentClass=None):
"""Load a module and retrieve a class (NOT an instance).
If the parentClass is supplied, className must be of parentClass
or a subclass of parentClass (or None is returned).
"""
aClass = _get_func(fullClassName)
# Assert that the class is a subclass of parentClass.
if parentClass is not None:
if not issubclass(aClass, parentClass):
raise TypeError(u"%s is not a subclass of %s" %
(fullClassName, parentClass))
# Return a reference to the class itself, not an instantiated object.
return aClass
######################
## Usage ##
######################
class StorageManager: pass
class StorageManagerMySQL(StorageManager): pass
def storage_object(aFullClassName, allOptions={}):
aStoreClass = _get_class(aFullClassName, StorageManager)
return aStoreClass(allOptions)
これはうまくいくはずです
path = os.path.join('./path/to/folder/with/py/files', '*.py')
for infile in glob.glob(path):
basename = os.path.basename(infile)
basename_without_extension = basename[:-3]
# http://docs.python.org/library/imp.html?highlight=imp#module-imp
imp.load_source(basename_without_extension, infile)
非常に簡単な方法: 相対パス ../../MyLibs/pyfunc.py でファイルをインポートしたいとします。
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
しかし、ガードなしでそれを行うと、最終的に非常に長いパスを取得できます.
これらは、pathlib のみを使用する私の 2 つのユーティリティ関数です。パスからモジュール名を推測します。
デフォルトでは、フォルダーからすべての Python ファイルを再帰的に読み込み、init .py を親フォルダー名に置き換えます。ただし、パスやグロブを指定して特定のファイルを選択することもできます。
from pathlib import Path
from importlib.util import spec_from_file_location, module_from_spec
from typing import Optional
def get_module_from_path(path: Path, relative_to: Optional[Path] = None):
if not relative_to:
relative_to = Path.cwd()
abs_path = path.absolute()
relative_path = abs_path.relative_to(relative_to.absolute())
if relative_path.name == "__init__.py":
relative_path = relative_path.parent
module_name = ".".join(relative_path.with_suffix("").parts)
mod = module_from_spec(spec_from_file_location(module_name, path))
return mod
def get_modules_from_folder(folder: Optional[Path] = None, glob_str: str = "*/**/*.py"):
if not folder:
folder = Path(".")
mod_list = []
for file_path in sorted(folder.glob(glob_str)):
mod_list.append(get_module_from_path(file_path))
return mod_list
Cなどのようなファイルをロードする方法は次のとおりです。
from importlib.machinery import SourceFileLoader
import os
def LOAD(MODULE_PATH):
if (MODULE_PATH[0] == "/"):
FULL_PATH = MODULE_PATH;
else:
DIR_PATH = os.path.dirname (os.path.realpath (__file__))
FULL_PATH = os.path.normpath (DIR_PATH + "/" + MODULE_PATH)
return SourceFileLoader (FULL_PATH, FULL_PATH).load_module ()
実装:
Y = LOAD("../Z.py")
A = LOAD("./A.py")
D = LOAD("./C/D.py")
A_ = LOAD("/IMPORTS/A.py")
Y.DEF();
A.DEF();
D.DEF();
A_.DEF();
各ファイルは次のようになります。
def DEF():
print("A");