フルパスで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 も参照してください。
Sys.pathに(impを使用するよりも)パスを追加することの利点は、単一のパッケージから複数のモジュールをインポートするときの処理が簡単になることです。例えば:
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
このようなことをして、設定ファイルが入っているディレクトリをPythonのロードパスに追加してから、通常はそのファイルの名前(この場合は "config")を知っていると仮定して通常のインポートを行います。
乱雑ですが、うまくいきます。
configfile = '~/config.py'
import os
import sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config
設定ファイル(特にたくさんの副作用と追加の複雑さを含んでいる)をインポートしたくない、あなたはそれを実行したい、そして結果の名前空間にアクセスすることができるように思えます。標準ライブラリは runpy.run_path の形式でそのためのAPIを提供します。
from runpy import run_path
settings = run_path("/path/to/file.py")
そのインターフェースはPython 2.7とPython 3.2以降で利用可能です。
@ SebastianRittauの素晴らしい答え (Python> 3.4用だと思います)} _の少し修正されたバージョンを思い付きました。これは spec_from_loader
を使って任意の拡張子のファイルをモジュールとしてロードできるようにします。 spec_from_file_location
の代わりに_:
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py"))
mod = module_from_spec(spec)
spec.loader.exec_module(mod)
明示的な SourceFileLoader
でパスをエンコードすることの利点は、 machines が拡張子からファイルの種類を判断しようとしないことです。これは、このメソッドを使用して.txt
ファイルのようなものをロードできることを意味しますが、spec_from_file_location
は .txt
にないため、ローダーを指定せずにimportlib.machinery.SOURCE_SUFFIXES
でそれを実行することはできません。
あなたはロードまたはインポートを意味しますか?
Sys.pathリストを操作してモジュールへのパスを指定してから、モジュールをインポートすることができます。たとえば、次の場所にモジュールがあるとします。
/foo/bar.py
あなたがすることができます:
import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar
最上位モジュールがファイルではなく__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属性として現れなければなりません 。
モジュールをインポートするには、一時的または恒久的にそのディレクトリを環境変数に追加する必要があります。
import sys
sys.path.append("/path/to/my/modules/")
import my_module
次の行をあなたの.bashrc
ファイル(Linuxの場合)に追加し、ターミナルでsource ~/.bashrc
を実行してください:
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
クレジット/出典: saarrrr 、 別のstackexchangeの質問
これは、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())
私はそれをテストしました。それは醜いかもしれませんが、これまでのところすべてのバージョンで動作する唯一のものです。
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:
raise ImportError
import_file('/home/somebody/somemodule.py')
指定したモジュールをロードするために imp.find_module()
と imp.load_module()
を使うことができると私は信じています。モジュール名をパスから分割する必要があります。つまり、/home/mypath/mymodule.py
をロードしたい場合は、次のようにします。
imp.find_module('mymodule', '/home/mypath/')
...しかし、これで仕事は終わりです。
Pythonモジュールtest.pyを作成します
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
Pythonモジュールtest_check.pyを作成します
from test import Client1
from test import Client2
from test import test3
インポートしたモジュールをmoduleからインポートすることができます。
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!
これはうまくいくはずです
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)
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の解決策はコマンドラインではうまくいったが、プログラムの中ではうまくいかなかったことに気づいた。
与えられたファイル名からモジュールをインポートするには、一時的にパスを拡張し、システムブロックをfinallyブロック referenceに復元します。
filename = "directory/module.py"
directory, module_name = os.path.split(filename)
module_name = os.path.splitext(module_name)[0]
path = list(sys.path)
sys.path.insert(0, directory)
try:
module = __import__(module_name)
finally:
sys.path[:] = path # restore
実行時にパッケージモジュールをインポートする(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)
Linuxでは、Pythonスクリプトが置かれているディレクトリにシンボリックリンクを追加することはうまくいきます。
すなわち:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
pythonは/absolute/path/to/script/module.pyc
を作成し、/absolute/path/to/module/module.py
の内容を変更するとそれを更新します
それからmypythonscript.pyに以下を含める
from module import *
私はあなたのために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
または
非常に簡単な方法:相対パスのファイルをインポートしたいとしましょう../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
しかし、あなたが警備員なしでそれを作るならば、あなたはついに非常に長い道筋を得ることができます
importlib
パッケージの代わりにimp
を使う簡単な解決法(Python 2.7でもテストされていますが、Python 3でも動作するはずです):
import importlib
dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py'
sys.path.append(dirname) # only directories should be added to PYTHONPATH
module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule'
module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")
これで、インポートしたモジュールの名前空間を直接使うことができます。
a = module.myvar
b = module.myfunc(a)
この解決策の利点は、 インポートしたいモジュールの実際の名前を知る必要さえない それを私たちのコードで使うために - 。これは便利です。モジュールのパスが設定可能な引数である場合。
うまくいったものが見つからなかったので、これを回答リストに追加しました。これにより、3.4のコンパイル済み(pyd)pythonモジュールのインポートが可能になります。
import sys
import importlib.machinery
def load_module(name, filename):
# If the Loader finds the module name in this list it will use
# module_name.__file__ instead so we need to delete it here
if name in sys.modules:
del sys.modules[name]
loader = importlib.machinery.ExtensionFileLoader(name, filename)
module = loader.load_module()
locals()[name] = module
globals()[name] = module
load_module('something', r'C:\Path\To\something.pyd')
something.do_something()
この回答は、コメントに答えたSebastian Rittauの回答を補足するものです。これはpythonのモジュール名にファイル名をつける簡単で汚い方法です - それは__init__.py
ファイルのないディレクトリを見つけてそれをファイル名に戻すまでツリーを上がるだけです。 Python 3.4以降(pathlibを使用)では、Py2ユーザーは "imp"やその他の相対的なインポート方法を使用できるため、これは理にかなっています。
import pathlib
def likely_python_module(filename):
'''
Given a filename or Path, return the "likely" python module name. That is, iterate
the parent directories until it doesn't contain an __init__.py file.
:rtype: str
'''
p = pathlib.Path(filename).resolve()
paths = []
if p.name != '__init__.py':
paths.append(p.stem)
while True:
p = p.parent
if not p:
break
if not p.is_dir():
break
inits = [f for f in p.iterdir() if f.name == '__init__.py']
if not inits:
break
paths.append(p.stem)
return '.'.join(reversed(paths))
確かに改善の可能性があります、そしてオプションの__init__.py
ファイルは他の変更を必要とするかもしれません、しかしあなたが__init__.py
を一般に持っているなら、これはトリックをします。