2008-09-15 12 views

ответ

821

Для 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.

+30

Если бы я знал пространство имен - 'module.name' - я бы уже использовал `__import__`. – 2009-08-10 21:54:15

+39

@SridharRatnakumar значение первого аргумента `imp.load_source` только устанавливает` .__ name__` возвращаемого модуля. это не влияет на загрузку. – 2011-12-14 04:51:24

+14

@DanD. - первый аргумент `imp.load_source()` определяет ключ новой записи, созданной в словаре `sys.modules`, поэтому первый аргумент действительно влияет на загрузку. – 2013-04-21 16:32:33

8

Я считаю, что вы можете использовать imp.find_module() и imp.load_module() для загрузки указанного модуля. Вам нужно разделить имя модуля от пути, то есть, если вы хотите загрузить /home/mypath/mymodule.py вам нужно сделать:

imp.find_module('mymodule', '/home/mypath/') 

... но это должно получить работу.

15

Вы можете использовать метод

load_source(module_name, path_to_file) 

из imp module.

2

Импорт пакетов модулей во время выполнения (рецепт 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) 
15

Вы также можете сделать что-то вроде этого, и добавить в каталог, файл конфигурации сидит в к пути загрузки Python , а затем просто выполните обычный импорт, предполагая, что вы знаете имя файла заранее, в этом случае «config».

Беспокойный, но он работает.

configfile = '~/config.py' 

import os 
import sys 

sys.path.append(os.path.dirname(os.path.expanduser(configfile))) 

import config 
8

Вы имеете в виду груз или импорт?

Вы можете управлять списком sys.path, указывая путь к вашему модулю, а затем импортировать свой модуль. Например, если модуль по адресу:

/foo/bar.py 

Вы можете сделать:

import sys 
sys.path[0:0] = '/foo' # puts the /foo directory at the start of your path 
import bar 
+0

@Wheat Почему sys.path [0: 0] вместо sys.path [0]? – user618677 2012-01-09 06:56:32

+4

B/c sys.path [0] = xy перезаписывает первый элемент пути, а путь [0: 0] = xy эквивалентен path.insert (0, xy) – dom0 2012-11-15 14:16:10

+1

hm path.insert работал для меня, но [0 : 0] трюк не сделал. – jsh 2013-09-30 03:18:05

11
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') 
+31

Зачем писать 14 строк багги-кода, если эта проблема уже решена стандартной библиотекой? Вы не выполнили проверку ошибок в формате или содержимом full_path_to_module или os.whatever операций; и использование предложения catch-all `except:` редко бывает хорошей идеей. – 2013-06-07 19:17:48

279

Преимущество добавления пути к 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 
+3

Как мы используем `sys.path.append` для указания на один файл python вместо каталога? – Phani 2014-01-13 17:46:21

1

Я сделал пакет, который использует 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

или

http://code.google.com/p/import-file/

+1

os.chdir? (минимальные символы для утверждения комментариев). – ychaouche 2012-10-14 10:46:53

3

Это должно работать

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) 
+4

Более общий способ вырезать расширение: `name, ext = os.path.splitext (os.path.basename (infile))`. Ваш метод работает, потому что предыдущее ограничение на расширение .py. Кроме того, вы должны, вероятно, импортировать модуль в какую-либо переменную/словарь. – ReneSac 2012-12-06 13:16:36

2

Вы можете использовать модуль 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! 
1

В 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

от импорта модуля *

0

Лучший способ, я думаю, из официальной документации (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() 
3

Эта область 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. Я не претендую на то, чтобы понять, почему, но, похоже, работает изнутри программы. Я обнаружил, что решение Криса работало в командной строке, но не внутри программы.

3

Я не говорю, что это лучше, но для полноты картины, я хотел бы предложить функцию 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) 
3

Чтобы импортировать модуль из дано имя файла, вы можете временно продлить путь, и восстановление системного пути в окончательно блокировать 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 
-2

Это может быть очевидным, но в интерактивной оболочке:

cd path 
import module 
9

Похоже, что вы не хотите специально импортировать конфигурационный файл (который содержит множество побочных эффектов и дополнительных осложнений), вы просто хотите запустить его и иметь доступ к результирующему пространству имен. Стандартная библиотека предоставляет API специально для этого в виде runpy.run_path:

from runpy import run_path 
settings = run_path("/path/to/file.py") 

Этот интерфейс доступен в Python 2.7 и Python 3.2+

7

Вот код, который работает во всех версиях 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()) 

Я протестировал его. Это может быть уродливым, но до сих пор это единственное, что работает во всех версиях.

5

я пришел с немного измененной версией @ 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.

0

Добавьте это в список ответов, так как я не смог найти ничего, что сработало. Это позволит импорт скомпилированных (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() 
0

довольно простой способ: предположу, что вы хотите импортировать файл с относительным путем ../../MyLibs/pyfunc.py


libPath = '../../MyLibs' 
import sys 
if not libPath in sys.path: sys.path.append(libPath) 
import pyfunc as pf 

Но если вы сделаете это без охраны, вы можете, наконец, получить очень длинный путь.

 Смежные вопросы

  • Нет связанных вопросов^_^