Как загрузить модуль 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: использование (. Хотя это было устаревшим в Python 3.4)
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
Python 2 Использование:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Существуют эквивалентные функции удобства для скомпилированных файлов Python и DLL.
См. Также. http://bugs.python.org/issue21436.
Я считаю, что вы можете использовать imp.find_module()
и imp.load_module()
для загрузки указанного модуля. Вам нужно разделить имя модуля от пути, то есть, если вы хотите загрузить /home/mypath/mymodule.py
вам нужно сделать:
imp.find_module('mymodule', '/home/mypath/')
... но это должно получить работу.
Импорт пакетов модулей во время выполнения (рецепт 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)
Вы также можете сделать что-то вроде этого, и добавить в каталог, файл конфигурации сидит в к пути загрузки 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
@Wheat Почему sys.path [0: 0] вместо sys.path [0]? – user618677 2012-01-09 06:56:32
B/c sys.path [0] = xy перезаписывает первый элемент пути, а путь [0: 0] = xy эквивалентен path.insert (0, xy) – dom0 2012-11-15 14:16:10
hm path.insert работал для меня, но [0 : 0] трюк не сделал. – jsh 2013-09-30 03:18:05
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')
Зачем писать 14 строк багги-кода, если эта проблема уже решена стандартной библиотекой? Вы не выполнили проверку ошибок в формате или содержимом full_path_to_module или os.whatever операций; и использование предложения catch-all `except:` редко бывает хорошей идеей. – 2013-06-07 19:17:48
Преимущество добавления пути к 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
Как мы используем `sys.path.append` для указания на один файл python вместо каталога? – Phani 2014-01-13 17:46:21
Я сделал пакет, который использует 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
или
os.chdir? (минимальные символы для утверждения комментариев). – ychaouche 2012-10-14 10:46:53
Это должно работать
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)
Более общий способ вырезать расширение: `name, ext = os.path.splitext (os.path.basename (infile))`. Ваш метод работает, потому что предыдущее ограничение на расширение .py. Кроме того, вы должны, вероятно, импортировать модуль в какую-либо переменную/словарь. – ReneSac 2012-12-06 13:16:36
Вы можете использовать модуль 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!
В Linux, добавив символическую ссылку в каталоге вашего питона скрипт находится работой.
т.е.
пер -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
питон будет создавать/абсолютный/путь/к /script/module.pyc и будет обновлять его, если вы измените содержимое /absolute/path/to/module/module.py
затем включают следующее mypythonscript.py
от импорта модуля *
Лучший способ, я думаю, из официальной документации (29.1. imp — Access the import internals):
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()
Эта область Python 3.4, как представляется, чрезвычайно извилисты, чтобы понять! Однако с небольшим взломом с использованием кода от Криса Кэллоуэя в качестве запуска мне удалось что-то сделать. Вот основная функция.
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. Я не претендую на то, чтобы понять, почему, но, похоже, работает изнутри программы. Я обнаружил, что решение Криса работало в командной строке, но не внутри программы.
Я не говорю, что это лучше, но для полноты картины, я хотел бы предложить функцию exec
, доступный как в Python 2 и 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)
Чтобы импортировать модуль из дано имя файла, вы можете временно продлить путь, и восстановление системного пути в окончательно блокировать 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
Это может быть очевидным, но в интерактивной оболочке:
cd path
import module
Похоже, что вы не хотите специально импортировать конфигурационный файл (который содержит множество побочных эффектов и дополнительных осложнений), вы просто хотите запустить его и иметь доступ к результирующему пространству имен. Стандартная библиотека предоставляет API специально для этого в виде runpy.run_path:
from runpy import run_path
settings = run_path("/path/to/file.py")
Этот интерфейс доступен в Python 2.7 и Python 3.2+
Вот код, который работает во всех версиях Python, с 2.7 -3,5 и, возможно, даже другие.
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
Я протестировал его. Это может быть уродливым, но до сих пор это единственное, что работает во всех версиях.
я пришел с немного измененной версией @ 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
состоит в том, что machinery не будет пытаться определить тип файла из расширения. Это означает, что вы можете загрузить что-то вроде файла .txt
, используя этот метод, но вы не могли сделать это с помощью spec_from_file_location
без указания загрузчика, потому что .txt
не находится в importlib.machinery.SOURCE_SUFFIXES
.
Добавьте это в список ответов, так как я не смог найти ничего, что сработало. Это позволит импорт скомпилированных (PYD) питону модулей в 3.4:
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()
довольно простой способ: предположу, что вы хотите импортировать файл с относительным путем ../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Но если вы сделаете это без охраны, вы можете, наконец, получить очень длинный путь.
Если бы я знал пространство имен - 'module.name' - я бы уже использовал `__import__`. – 2009-08-10 21:54:15
@SridharRatnakumar значение первого аргумента `imp.load_source` только устанавливает` .__ name__` возвращаемого модуля. это не влияет на загрузку. – 2011-12-14 04:51:24
@DanD. - первый аргумент `imp.load_source()` определяет ключ новой записи, созданной в словаре `sys.modules`, поэтому первый аргумент действительно влияет на загрузку. – 2013-04-21 16:32:33