如何根据完整路径动态导入模块?

2024-11-18 08:41:00
admin
原创
14
摘要:问题描述:给定 Python 模块的完整路径,如何加载它?请注意,该文件可以位于文件系统中用户有访问权限的任何位置。另请参阅: 如何导入以字符串形式命名的模块?解决方案 1:让我们MyClass在 处module.name定义一个模块。下面是我们如何从这个模块/path/to/file.py导入MyClass...

问题描述:

给定 Python 模块的完整路径,如何加载它?

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


另请参阅: 如何导入以字符串形式命名的模块?


解决方案 1:

让我们MyClass在 处module.name定义一个模块。下面是我们如何从这个模块/path/to/file.py导入MyClass

对于 Python 3.5+ 使用(文档):

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

解决方案 2:

向 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

解决方案 3:

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

暂时地

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

永久

.bashrc在 Linux 中将以下行添加到您的(或替代)文件中,然后source ~/.bashrc在终端中执行(或替代):

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

来源/来源:saarrrr,另一个 Stack Exchange 问题

解决方案 4:

如果您的顶级模块不是文件,而是使用 __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 属性出现”,如此处所述。

解决方案 5:

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

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

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

解决方案 6:

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

虽然有点混乱,但是确实有效。

configfile = '~/config.py'

import os
import sys

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

import config

解决方案 7:

补充Sebastian Rittau的回答:至少对于CPython来说,有pydoc,虽然没有正式声明,但导入文件是它的作用:

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

PS.为了完整起见,在撰写本文时,有一个对当前实现的引用:pydoc.py ,我很高兴地说,与xkcd 1987一样,它没有使用问题 21436中提到的任何实现—— 至少不是逐字逐句的。

解决方案 8:

我想出了@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是,机器不会尝试根据扩展名找出文件的类型。这意味着您可以.txt使用此方法加载文件之类的东西,但如果不指定加载器,则无法执行此操作,spec_from_file_location因为.txt不在 中importlib.machinery.SOURCE_SUFFIXES

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

解决方案 9:

这里有一些适用于所有 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())

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

解决方案 10:

您可以使用

load_source(module_name, path_to_file)

imp 模块中的方法。

解决方案 11:

你是指加载还是导入?

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

/foo/bar.py

你可以这样做:

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

解决方案 12:

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

在这种情况utils.pysrc/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

解决方案 13:

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

解决方案 14:

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

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

...但是这样就应该可以完成工作了。

解决方案 15:

您可以使用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!

解决方案 16:

创建 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

我们可以从模块中导入被导入的模块。

解决方案 17:

有一个专门用于此的包:

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 也一样)中进行了测试,但根据项目的规模,它可能有些过度。

解决方案 18:

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 的解决方案在命令行上有效,但在程序内部无效。

解决方案 19:

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

解决方案 20:

这应该有效

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)

解决方案 21:

要从给定的文件名导入模块,您可以临时扩展路径,并在 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

解决方案 22:

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)

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

解决方案 23:

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

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

例如,如果您在"/path/to/module“中存储了一个具有功能的模块foo(),则可以通过执行以下操作来运行它:

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)

解决方案 24:

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

解决方案 25:

我已经编写了自己的基于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

测试.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`

测试库.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')

测试库.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')

测试库.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')

测试库.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')

输出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.4测试3.2.5`2.7.16`

优点

  • 可以将两个模块作为子模块导入,也可以将模块的内容导入到父模块(如果没有父模块,则导入到全局模块)。

  • 可以导入文件名中带有句点的模块。

  • 可以从任何扩展模块导入任何扩展模块。

  • 可以使用子模块的独立名称,而不是默认的没有扩展名的文件名(例如,testlib.std.pyas testlibtestlib.blabla.pyastestlib_blabla等等)。

  • 不依赖于sys.path或任何搜索路径存储。

  • 不需要在调用之间保存/恢复全局变量,如SOURCE_FILE和。SOURCE_DIR`tkl_import_module`

  • [for3.4.x及更高版本] 可以在嵌套调用中混合模块命名空间tkl_import_module(例如:named->local->namedlocal->named->local等等)。

  • [for3.4.x及更高版本] 可以自动将声明的全局变量/函数/类导出到通过tkl_import_module(通过tkl_declare_global函数)导入的所有子模块。

缺点

  • 不支持完整导入:

    • 忽略枚举和子类。

    • 忽略内置命令,因为每种类型都必须被专门复制。

    • 忽略不可轻易复制的类。

    • 避免复制内置模块(包括所有打包模块)。

  • [for3.3.x及以下] 要求tkl_import_module在所有模块中声明调用tkl_import_module(代码重复)

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

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

更新3

tkl_source_module增加了与 bash 类似的功能source,支持导入时的执行保护(通过模块合并而不是导入来实现)。

更新4

添加了将模块全局变量自动导出到所有子模块的功能tkl_declare_global,因为模块全局变量不是子模块的一部分,所以不可见。

更新 5

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

解决方案 26:

这是我对这个问题的 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(包括子模块)。

解决方案 27:

在 Linux 中,在 Python 脚本所在目录中添加符号链接是可行的。

IE:

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

/absolute/path/to/script/module.pyc如果您更改的内容,Python 解释器将创建并更新它/absolute/path/to/module/module.py

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

from module import *

解决方案 28:

这将允许在 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:PathTosomething.pyd')
something.do_something()

解决方案 29:

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

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

但如果你不带守卫的话,你最终会得到一条很长的路。

解决方案 30:

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

默认情况下,它会递归加载文件夹中的所有 Python 文件,并用父文件夹名称替换init.py。但您也可以提供路径和/或 glob 来选择某些特定文件。

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
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用