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

发布于 2024-07-05 19:01:51 字数 193 浏览 16 评论 0原文

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

请注意,该文件可以位于文件系统中用户具有访问权限的任何位置。


另请参阅: 如何导入名称为字符串的模块?

How do I load a Python module given its full path?

Note that the file can be anywhere in the filesystem where the user has access rights.


See also: How to import a module given its name as string?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

淡淡離愁欲言轉身 2024-07-12 19:01:52

如果您的顶级模块不是文件,而是使用 __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'未加载,无法执行相对导入”。 所以加载之前需要先绑定名字。 这样做的原因是相对导入系统的基本不变量:“不变量的持有是,如果你有 sys.modules['spam'] 和 sys.modules['spam.foo'] (就像你在上述导入之后所做的那样) ),后者必须显示为前者的 foo 属性”如此处讨论。

If your top-level module is not a file but is packaged as a directory with __init__.py, then the accepted solution almost works, but not quite. In Python 3.5+ the following code is needed (note the added line that begins with '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)

Without this line, when exec_module is executed, it tries to bind relative imports in your top level __init__.py to the top level module name -- in this case "mymodule". But "mymodule" isn't loaded yet so you'll get the error "SystemError: Parent module 'mymodule' not loaded, cannot perform relative import". So you need to bind the name before you load it. The reason for this is the fundamental invariant of the relative import system: "The invariant holding is that if you have sys.modules['spam'] and sys.modules['spam.foo'] (as you would after the above import), the latter must appear as the foo attribute of the former" as discussed here.

调妓 2024-07-12 19:01:52

您还可以执行类似的操作,并将配置文件所在的目录添加到 Python 加载路径中,然后执行正常导入,假设您提前知道文件的名称,在本例中为“config”。

凌乱,但它有效。

configfile = '~/config.py'

import os
import sys

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

import config

You can also do something like this and add the directory that the configuration file is sitting in to the Python load path, and then just do a normal import, assuming you know the name of the file in advance, in this case "config".

Messy, but it works.

configfile = '~/config.py'

import os
import sys

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

import config
人间☆小暴躁 2024-07-12 19:01:52

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

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

该接口在 Python 2.7 和 Python 3.2+ 中可用。

It sounds like you don't want to specifically import the configuration file (which has a whole lot of side effects and additional complications involved). You just want to run it, and be able to access the resulting namespace. The standard library provides an API specifically for that in the form of runpy.run_path:

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

That interface is available in Python 2.7 and Python 3.2+.

一身骄傲 2024-07-12 19:01:52

添加到 Sebastian Rittau'答案:
至少对于 CPython 来说,有 pydoc,虽然没有正式声明,但导入文件就是它的作用:

from pydoc import importfile
module = importfile('/path/to/module.py')

PS。为了完整起见,有在撰写本文时对当前实现的引用: pydoc.py ,我很高兴地说,按照 xkcd 1987 的脉络,它没有使用issue 21436 中提到的实现——至少不是逐字的。

To add to Sebastian Rittau's answer:
At least for CPython, there's pydoc, and, while not officially declared, importing files is what it does:

from pydoc import importfile
module = importfile('/path/to/module.py')

PS. For the sake of completeness, there's a reference to the current implementation at the moment of writing: pydoc.py, and I'm pleased to say that in the vein of xkcd 1987 it uses neither of the implementations mentioned in issue 21436 -- at least, not verbatim.

酷遇一生 2024-07-12 19:01:52

我提出了 @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)

以显式方式编码路径的优点 SourceFileLoadermachinery 不会尝试从扩展名中找出文件的类型。 这意味着您可以使用此方法加载诸如 .txt 文件之类的内容,但如果不指定加载程序,则无法使用 spec_from_file_location 来执行此操作,因为 .txt 不在 importlib.machinery.SOURCE_SUFFIXES

我已将基于此的实现以及 @SamGrondahl 的有用修改放入我的实用程序库中,哈吉斯。 该函数称为 haggis.load.load_module。 它添加了一些巧妙的技巧,例如在加载模块名称空间时将变量注入到模块名称空间中的能力。

I have come up with a slightly modified version of @SebastianRittau's wonderful answer (for Python > 3.4 I think), which will allow you to load a file with any extension as a module using spec_from_loader instead of 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)

The advantage of encoding the path in an explicit SourceFileLoader is that the machinery will not try to figure out the type of the file from the extension. This means that you can load something like a .txt file using this method, but you could not do it with spec_from_file_location without specifying the loader because .txt is not in importlib.machinery.SOURCE_SUFFIXES.

I've placed an implementation based on this, and @SamGrondahl's useful modification into my utility library, haggis. The function is called haggis.load.load_module. It adds a couple of neat tricks, like the ability to inject variables into the module namespace as it is loaded.

时光是把杀猪刀 2024-07-12 19:01:52

下面是一些适用于所有 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())

我测试过。 它可能很难看,但到目前为止它是唯一一个适用于所有版本的。

Here is some code that works in all Python versions, from 2.7-3.5 and probably even others.

config_file = "/tmp/config.py"
with open(config_file) as f:
    code = compile(f.read(), config_file, 'exec')
    exec(code, globals(), locals())

I tested it. It may be ugly, but so far it is the only one that works in all versions.

五里雾 2024-07-12 19:01:52

您可以使用 pkgutil 模块(特别是 < code>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!

You can use the pkgutil module (specifically the walk_packages method) to get a list of the packages in the current directory. From there it's trivial to use the importlib machinery to import the modules you want:

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!
ι不睡觉的鱼゛ 2024-07-12 19:01:52

我相信你可以使用 imp.find_module() imp.load_module() 加载指定的模块。 您需要将模块名称从路径中分离出来,即如果您想加载 /home/mypath/mymodule.py 您需要执行

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

以下操作: ...但这应该得到任务完成。

I believe you can use imp.find_module() and imp.load_module() to load the specified module. You'll need to split the module name off of the path, i.e. if you wanted to load /home/mypath/mymodule.py you'd need to do:

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

...but that should get the job done.

以往的大感动 2024-07-12 19:01:52

您可以使用 __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')

You can do this using __import__ and 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')
场罚期间 2024-07-12 19:01:52

如果我们有脚本在同一个项目但是在不同的目录意味着,我们可以通过以下方法解决这个问题。

在这种情况下,utils.py位于src/main/util/

import sys
sys.path.append('./')

import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method

If we have scripts in the same project but in different directory means, we can solve this problem by the following method.

In this situation utils.py is in src/main/util/

import sys
sys.path.append('./')

import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method
紧拥背影 2024-07-12 19:01:52

您可以使用

load_source(module_name, path_to_file)

imp 模块 中的方法。

You can use the

load_source(module_name, path_to_file)

method from the imp module.

〃温暖了心ぐ 2024-07-12 19:01:52

你的意思是加载还是导入?

您可以操作 sys.path 列表指定模块的路径,然后导入您的模块。 例如,给定一个模块:

/foo/bar.py

您可以这样做:

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

Do you mean load or import?

You can manipulate the sys.path list specify the path to your module, and then import your module. For example, given a module at:

/foo/bar.py

You could do:

import sys
sys.path[0:0] = ['/foo'] # Puts the /foo directory at the start of your path
import bar
无声静候 2024-07-12 19:01:52

有一个 package 专门用于此目的:

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')

它已在 Python 版本(Jython 和 PyPy 也是如此)上进行了测试,但是根据您项目的规模,这可能有点过分了。

There's a package that's dedicated to this specifically:

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')

It's tested across Python versions (Jython and PyPy too), but it might be overkill depending on the size of your project.

南街女流氓 2024-07-12 19:01:52

创建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中导入导入的模块。

Create Python module test.py:

import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3

Create Python module test_check.py:

from test import Client1
from test import Client2
from test import test3

We can import the imported module from module.

终陌 2024-07-12 19:01:52

使用 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)

此解决方案的优点是我们甚至不需要知道要导入的模块的实际名称,以便在我们的代码中使用它。 这很有用,例如在模块的路径是可配置参数的情况下。

A simple solution using importlib instead of the imp package (tested for Python 2.7, although it should work for Python 3 too):

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")

Now you can directly use the namespace of the imported module, like this:

a = module.myvar
b = module.myfunc(a)

The advantage of this solution is that we don't even need to know the actual name of the module we would like to import, in order to use it in our code. This is useful, e.g. in case the path of the module is a configurable argument.

假装爱人 2024-07-12 19:01:52

这应该有效

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)

This should work

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)
飘过的浮云 2024-07-12 19:01:52

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

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

To import a module from a given filename, you can temporarily extend the path, and restore the system path in the finally block 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
方觉久 2024-07-12 19:01:52

我为您制作了一个使用 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/

I made a package that uses imp for you. I call it import_file and this is how it's used:

>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')

You can get it at:

http://pypi.python.org/pypi/import_file

or at

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

云胡 2024-07-12 19:01:52

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 中未弃用的模块。 我并不假装理解为什么,但它似乎是在程序内工作的。 我发现克里斯的解决方案可以在命令行上运行,但不能在程序内部运行。

This area of Python 3.4 seems to be extremely tortuous to understand! However with a bit of hacking using the code from Chris Calloway as a start I managed to get something working. Here's the basic function.

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

This appears to use non-deprecated modules from Python 3.4. I don't pretend to understand why, but it seems to work from within a program. I found Chris' solution worked on the command line but not from inside a program.

醉梦枕江山 2024-07-12 19:01:52

我并不是说它更好,但为了完整起见,我想建议 exec 函数,在 Python 2 和 Python 3 中均可用。

exec 允许您在全局范围或以字典形式提供的内部范围内执行任意代码。

例如,如果您有一个使用函数 foo() 存储在 "/path/to/module" 中的模块,则可以通过执行以下操作来运行它

module = dict()
with open("/path/to/module") as f:
    exec(f.read(), module)
module['foo']()

:更明确的是,您正在动态加载代码,并授予您一些额外的功能,例如提供自定义内置函数的能力。

如果通过属性而不是键进行访问对您来说很重要,您可以为全局变量设计一个自定义字典类,它提供此类访问权限,例如:

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

I'm not saying that it is better, but for the sake of completeness, I wanted to suggest the exec function, available in both Python 2 and Python 3.

exec allows you to execute arbitrary code in either the global scope, or in an internal scope, provided as a dictionary.

For example, if you have a module stored in "/path/to/module" with the function foo(), you could run it by doing the following:

module = dict()
with open("/path/to/module") as f:
    exec(f.read(), module)
module['foo']()

This makes it a bit more explicit that you're loading code dynamically, and grants you some additional power, such as the ability to provide custom builtins.

And if having access through attributes, instead of keys is important to you, you can design a custom dict class for the globals, that provides such access, e.g.:

class MyModuleClass(dict):
    def __getattr__(self, name):
        return self.__getitem__(name)
逆光飞翔i 2024-07-12 19:01:52

在运行时导入包模块(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)

Import package modules at runtime (Python recipe)

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)
那小子欠揍 2024-07-12 19:01:52

我基于 importlib 模块编写了自己的全局和可移植导入函数,用于:

  • 能够将两个模块作为子模块导入,并将模块的内容导入到父模块(或全局变量)中。如果没有父模块)。
  • 能够导入文件名中带有句点字符的模块。
  • 能够导入具有任何扩展名的模块。
  • 能够为子模块使用独立名称,而不是默认情况下不带扩展名的文件名。
  • 能够根据先前导入的模块定义导入顺序,而不是依赖于 sys.path 或任何搜索路径存储。

示例目录结构:

<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

实现:

最新更改存储: https://github.com/andry81/tacklelib/tree/HEAD/python/tacklelib/tacklelib.py

test.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`

testlib.py :

# 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')

testlib.std1.py:

# 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')

testlib.std2.py:

# 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')

testlib.std3.py:

# 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')

输出 (< code>3.7.4):

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

在 Python 3.7.43.2.52.7.16 中测试

优点

  • 可以将两个模块作为子模块导入,并且可以将模块的内容导入到父模块(如果没有父模块,则导入到全局变量中)。
  • 可以导入文件名中带有句点的模块。
  • 可以从任何扩展模块导入任何扩展模块。
  • 可以为子模块使用独立名称,而不是默认情况下不带扩展名的文件名(例如,testlib.std.py as testlibtestlib.std.py)。 blabla.py 为 testlib_blabla 等)。
  • 不依赖于 sys.path 或任何搜索路径存储。
  • 不需要在调用 tkl_import_module 之间保存/恢复全局变量,例如 SOURCE_FILESOURCE_DIR
  • [对于 3.4.x 及更高版本] 可以在嵌套的 tkl_import_module 调用中混合模块命名空间(例如:named->local->named本地->命名->本地等等)。
  • [对于 3.4.x 及更高版本] 可以将声明的全局变量/函数/类自动导出到通过 tkl_import_module 导入的所有子模块(通过 tkl_declare_global 函数)。

缺点

  • 不支持完全导入:
    • 忽略枚举和子类。
    • 忽略内置函数,因为每种类型都必须进行独占复制。
    • 忽略不可简单复制的类。
    • 避免复制内置模块,包括所有打包模块。
  • [对于 3.3.x 及更低版本] 需要在调用 tkl_import_module 的所有模块中声明 tkl_import_module(代码重复)

更新 1, 2(仅适用于 3.4.x 及更高版本):

在 Python 3.4 及更高版本中,您可以通过声明 来绕过在每个模块中声明 tkl_import_module 的要求tkl_import_module 在顶级模块中,该函数将在一次调用中将自身注入到所有子模块中(这是一种自部署导入)。

更新 3

添加函数 tkl_source_module 与 bash source 类似,并在导入时支持执行保护(通过模块合并而不是导入实现)。

更新 4

添加了函数 tkl_declare_global 以自动将模块全局变量导出到所有子模块,其中模块全局变量因不属于子模块而不可见。

更新5

所有函数已移至tracelib库中,请参阅上面的链接。

I have written my own global and portable import function, based on importlib module, for:

  • Be able to import both modules as submodules and to import the content of a module to a parent module (or into a globals if has no parent module).
  • Be able to import modules with a period characters in a file name.
  • Be able to import modules with any extension.
  • Be able to use a standalone name for a submodule instead of a file name without extension which is by default.
  • Be able to define the import order based on previously imported module instead of dependent on sys.path or on a what ever search path storage.

The examples directory structure:

<root>
 |
 +- test.py
 |
 +- testlib.py
 |
 +- /std1
 |   |
 |   +- testlib.std1.py
 |
 +- /std2
 |   |
 |   +- testlib.std2.py
 |
 +- /std3
     |
     +- testlib.std3.py

Inclusion dependency and order:

test.py
  -> testlib.py
    -> testlib.std1.py
      -> testlib.std2.py
    -> testlib.std3.py

Implementation:

Latest changes store: https://github.com/andry81/tacklelib/tree/HEAD/python/tacklelib/tacklelib.py

test.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`

testlib.py:

# 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')

testlib.std1.py:

# 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')

testlib.std2.py:

# 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')

testlib.std3.py:

# 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')

Output (3.7.4):

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

Tested in Python 3.7.4, 3.2.5, 2.7.16

Pros:

  • Can import both module as a submodule and can import content of a module to a parent module (or into a globals if has no parent module).
  • Can import modules with periods in a file name.
  • Can import any extension module from any extension module.
  • Can use a standalone name for a submodule instead of a file name without extension which is by default (for example, testlib.std.py as testlib, testlib.blabla.py as testlib_blabla and so on).
  • Does not depend on a sys.path or on a what ever search path storage.
  • Does not require to save/restore global variables like SOURCE_FILE and SOURCE_DIR between calls to tkl_import_module.
  • [for 3.4.x and higher] Can mix the module namespaces in nested tkl_import_module calls (ex: named->local->named or local->named->local and so on).
  • [for 3.4.x and higher] Can auto export global variables/functions/classes from where being declared to all children modules imported through the tkl_import_module (through the tkl_declare_global function).

Cons:

  • Does not support complete import:
    • Ignores enumerations and subclasses.
    • Ignores builtins because each what type has to be copied exclusively.
    • Ignore not trivially copiable classes.
    • Avoids copying builtin modules including all packaged modules.
  • [for 3.3.x and lower] Require to declare tkl_import_module in all modules which calls to tkl_import_module (code duplication)

Update 1,2 (for 3.4.x and higher only):

In Python 3.4 and higher you can bypass the requirement to declare tkl_import_module in each module by declare tkl_import_module in a top level module and the function would inject itself to all children modules in a single call (it's a kind of self deploy import).

Update 3:

Added function tkl_source_module as analog to bash source with support execution guard upon import (implemented through the module merge instead of import).

Update 4:

Added function tkl_declare_global to auto export a module global variable to all children modules where a module global variable is not visible because is not a part of a child module.

Update 5:

All functions has moved into the tacklelib library, see the link above.

随遇而安 2024-07-12 19:01:52

一种非常简单的方法:假设您想要使用相对路径 ../../MyLibs/pyfunc.py 导入文件,

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

但是如果您在没有防护的情况下进行导入,您最终可以获得很长的路径。

A quite simple way: suppose you want import file with relative path ../../MyLibs/pyfunc.py

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

But if you make it without a guard you can finally get a very long path.

许一世地老天荒 2024-07-12 19:01:52

这将允许在 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()

This will allow imports of compiled (pyd) Python modules in 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()
血之狂魔 2024-07-12 19:01:52

在 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 *

In Linux, adding a symbolic link in the directory your Python script is located works.

I.e.:

ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py

The Python interpreter will create /absolute/path/to/script/module.pyc and will update it if you change the contents of /absolute/path/to/module/module.py.

Then include the following in file mypythonscript.py:

from module import *
策马西风 2024-07-12 19:01:52

这是我对这个问题的 2024 年解决方案 - 不需要 .py 文件的路径,模块文件夹父级的路径就足够了。

import importlib
import importlib.machinery
import importlib.util

pkg = "mypkg"
spec = importlib.machinery.PathFinder().find_spec(pkg, ["/path/to/mypkg-parent"])
mod = importlib.util.module_from_spec(spec)
sys.modules[pkg] = mod  # needed for exec_module to work
spec.loader.exec_module(mod)
sys.modules[pkg] = importlib.import_module(pkg)

最后一条语句是必要的,以确保完整的模块存在于 sys.modules 中(包括子模块)。

Here's my 2024 solution to this question - does not require path to a .py file, path to the parent of the module folder is sufficient.

import importlib
import importlib.machinery
import importlib.util

pkg = "mypkg"
spec = importlib.machinery.PathFinder().find_spec(pkg, ["/path/to/mypkg-parent"])
mod = importlib.util.module_from_spec(spec)
sys.modules[pkg] = mod  # needed for exec_module to work
spec.loader.exec_module(mod)
sys.modules[pkg] = importlib.import_module(pkg)

The last statement is necessary to ensure that the full module is present in sys.modules (including submodules).

卖梦商人 2024-07-12 19:01:52

这是我仅使用 pathlib 的两个实用函数。 它从路径推断模块名称。

默认情况下,它会递归地加载文件夹中的所有 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

These are my two utility functions using only pathlib. It infers the module name from the path.

By default, it recursively loads all Python files from folders and replaces init.py by the parent folder name. But you can also give a Path and/or a glob to select some specific files.

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
茶色山野 2024-07-12 19:01:51

让我们在 /path/to/file.py 定义的 module.name 模块中添加 MyClass 。 下面是我们如何从此模块导入 MyClass

对于 Python 3.5+ 使用 (docs):

import importlib.util
import sys
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
sys.modules["module.name"] = foo
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

Let's have MyClass in module.name module defined at /path/to/file.py. Below is how we import MyClass from this module

For Python 3.5+ use (docs):

import importlib.util
import sys
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
sys.modules["module.name"] = foo
spec.loader.exec_module(foo)
foo.MyClass()

For Python 3.3 and 3.4 use:

from importlib.machinery import SourceFileLoader

foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()

(Although this has been deprecated in Python 3.4.)

For Python 2 use:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

There are equivalent convenience functions for compiled Python files and DLLs.

See also http://bugs.python.org/issue21436.

浮华 2024-07-12 19:01:51

向 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

The advantage of adding a path to sys.path (over using imp) is that it simplifies things when importing more than one module from a single package. For example:

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
转身泪倾城 2024-07-12 19:01:51

要导入模块,您需要将其目录临时或永久添加到环境变量中。

临时

import sys
sys.path.append("/path/to/my/modules/")
import my_module

永久

将以下行添加到 Linux 中的 .bashrc(或替代)文件中
并在终端中执行 source ~/.bashrc (或替代方案):

export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"

Credit/Source: saarrrrr, 另一个 StackExchange 问题

To import your module, you need to add its directory to the environment variable, either temporarily or permanently.

Temporarily

import sys
sys.path.append("/path/to/my/modules/")
import my_module

Permanently

Adding the following line to your .bashrc (or alternative) file in Linux
and excecute source ~/.bashrc (or alternative) in the terminal:

export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"

Credit/Source: saarrrr, another Stack Exchange question

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文