Python 如何在给定完整路径的情况下导入模块?

Python 如何在给定完整路径的情况下导入模块?,python,configuration,python-import,python-module,Python,Configuration,Python Import,Python Module,如何加载给定完整路径的Python模块?请注意,文件可以位于文件系统中的任何位置,因为它是一个配置选项。我相信您可以使用和加载指定的模块。您需要将模块名称从路径中分离出来,即,如果要加载/home/mypath/mymodule.py,则需要执行以下操作: imp.find_module('mymodule', '/home/mypath/') …但这应该可以完成工作。对于Python 3.5+使用: import importlib.util spec = importlib.util.sp

如何加载给定完整路径的Python模块?请注意,文件可以位于文件系统中的任何位置,因为它是一个配置选项。

我相信您可以使用和加载指定的模块。您需要将模块名称从路径中分离出来,即,如果要加载
/home/mypath/mymodule.py
,则需要执行以下操作:

imp.find_module('mymodule', '/home/mypath/')
…但这应该可以完成工作。

对于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()
(尽管在Python3.4中这一点已被弃用。)

对于Python 2,请使用:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
对于编译后的Python文件和DLL,有一些等效的方便函数

另请参见。

您可以使用

load_source(module_name, path_to_file) 

方法。

在运行时导入包模块(Python配方)


您还可以执行类似的操作,将配置文件所在的目录添加到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

您可以使用导入和chdir来实现这一点

def导入文件(到模块的完整路径):
尝试:
导入操作系统
module_dir,module_file=os.path.split(到模块的完整路径)
模块名称,模块ext=os.path.splitext(模块文件)
save_cwd=os.getcwd()
os.chdir(模块_dir)
模块\对象=\导入\导入(模块\名称)
模块对象。\uuuuu文件\uuuuuu=到模块的完整路径
globals()[module_name]=module_obj
os.chdir(保存cwd)
例外情况除外,如e:
提出建议(e)
返回模块
导入文件('/home/someone/somemodule.py')

将路径添加到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

我为您制作了一个使用
imp
的软件包。我称之为
import\u file
,它的用法如下:

>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
您可以在以下网址获得:

这应该行得通

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)

您可以使用
pkgutil
模块(特别是方法)获取当前目录中的包列表。从这里开始,使用
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中,在python脚本所在的目录中添加符号链接是可行的

即:

python将创建
/absolute/path/to/script/module.pyc
,如果您更改
/absolute/path/to/module/module.py

然后在mypythonscript.py中包含以下内容

from module import *

Python3.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的解决方案是在命令行上运行的,但不是在程序内部运行的。

我不是说它更好,但为了完整性,我想推荐在python 2和3中都可用的函数。
exec
允许您在全局范围内或作为字典提供的内部范围内执行任意代码

例如,如果使用函数
foo()
,将模块存储在
“/path/to/module
”中,则可以通过执行以下操作来运行该模块:

module = dict()
with open("/path/to/module") as f:
    exec(f.read(), module)
module['foo']()
这使得动态加载代码更加明确,并赋予您一些额外的功能,例如提供自定义内置代码的能力

如果通过属性而不是键进行访问对您来说很重要,您可以为globals设计一个自定义dict类,以提供此类访问,例如:

class MyModuleClass(dict):
    def __getattr__(self, name):
        return self.__getitem__(name)

要从给定文件名导入模块,可以临时扩展路径,并在finally块中恢复系统路径


听起来您不想专门导入配置文件(这会带来很多副作用和额外的复杂性),您只想运行它,并能够访问生成的名称空间。标准库提供了一个专门用于以下形式的API:


该接口在Python2.7和Python3.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())

我测试过了。它可能很难看,但到目前为止,它是唯一一个在所有版本中都能工作的版本。

我提出了一个稍微修改过的版本(我想是Python>3.4),它将允许您将具有任何扩展名的文件作为模块加载,而不是使用:


以显式方式编码路径的优点是,不会试图从扩展名中找出文件的类型。这意味着您可以使用此方法加载类似于
.txt
文件的内容,但如果不指定加载程序,则无法使用
spec\u from\u file\u location
加载,因为
.txt
不在。将其添加到答案列表中,因为我找不到任何有效的答案。这将允许在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()

非常简单的方法:假设您希望导入具有相对路径.././MyLibs/pyfunc.py的文件


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

但是,如果您在没有保护的情况下实现了它,您最终可以获得一条非常长的路径

如果您的顶级模块不是一个文件,而是用_uinit_; py.py打包为一个目录,那么可以接受的解决方案几乎可以工作,但并不完全有效。在Python 3.5+中,需要以下代码(注意以“sys.modules”开头的添加行):

如果没有这一行,当执行exec_模块时,它会尝试将顶层_init__uuu.py中的相对导入绑定到顶层模块名--in
from runpy import run_path
settings = run_path("/path/to/file.py")
config_file = "/tmp/config.py"
with open(config_file) as f:
    code = compile(f.read(), config_file, 'exec')
    exec(code, globals(), locals())
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)
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()

libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
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)
a = module.myvar
b = module.myfunc(a)
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))
import sys
sys.path.append("/path/to/my/modules/")
import my_module
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
from test import Client1
from test import Client2
from test import test3
<root>
 |
 +- test.py
 |
 +- testlib.py
 |
 +- /std1
 |   |
 |   +- testlib.std1.py
 |
 +- /std2
 |   |
 |   +- testlib.std2.py
 |
 +- /std3
     |
     +- testlib.std3.py
test.py
  -> testlib.py
    -> testlib.std1.py
      -> testlib.std2.py
    -> testlib.std3.py 
import os, sys, inspect, copy

SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("test::SOURCE_FILE: ", SOURCE_FILE)

# portable import to the global space
sys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directory
import tacklelib as tkl

tkl.tkl_init(tkl)

# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()

tkl_import_module(SOURCE_DIR, 'testlib.py')

print(globals().keys())

testlib.base_test()
testlib.testlib_std1.std1_test()
testlib.testlib_std1.testlib_std2.std2_test()
#testlib.testlib.std3.std3_test()                             # does not reachable directly ...
getattr(globals()['testlib'], 'testlib.std3').std3_test()     # ... but reachable through the `globals` + `getattr`

tkl_import_module(SOURCE_DIR, 'testlib.py', '.')

print(globals().keys())

base_test()
testlib_std1.std1_test()
testlib_std1.testlib_std2.std2_test()
#testlib.std3.std3_test()                                     # does not reachable directly ...
globals()['testlib.std3'].std3_test()                         # ... but reachable through the `globals` + `getattr`
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("1 testlib::SOURCE_FILE: ", SOURCE_FILE)

tkl_import_module(SOURCE_DIR + '/std1', 'testlib.std1.py', 'testlib_std1')

# SOURCE_DIR is restored here
print("2 testlib::SOURCE_FILE: ", SOURCE_FILE)

tkl_import_module(SOURCE_DIR + '/std3', 'testlib.std3.py')

print("3 testlib::SOURCE_FILE: ", SOURCE_FILE)

def base_test():
  print('base_test')
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("testlib.std1::SOURCE_FILE: ", SOURCE_FILE)

tkl_import_module(SOURCE_DIR + '/../std2', 'testlib.std2.py', 'testlib_std2')

def std1_test():
  print('std1_test')
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("testlib.std2::SOURCE_FILE: ", SOURCE_FILE)

def std2_test():
  print('std2_test')
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)

print("testlib.std3::SOURCE_FILE: ", SOURCE_FILE)

def std3_test():
  print('std3_test')
test::SOURCE_FILE:  <root>/test01/test.py
import : <root>/test01/testlib.py as testlib -> []
1 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE:  <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE:  <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib'])
base_test
std1_test
std2_test
std3_test
import : <root>/test01/testlib.py as . -> []
1 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE:  <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE:  <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE:  <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE:  <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib', 'testlib_std1', 'testlib.std3', 'base_test'])
base_test
std1_test
std2_test
std3_test
from thesmuggler import smuggle

# À la `import weapons`
weapons = smuggle('weapons.py')

# À la `from contraband import drugs, alcohol`
drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py')

# À la `from contraband import drugs as dope, alcohol as booze`
dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')
import sys
sys.path.append('./')

import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method
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
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");