在所有条件下强制从文件名导入模块(更改模块,更改文件名)

时间:2016-05-01 07:54:52

标签: python python-import

我正在寻找一个从文件名加载和返回模块的Python例程,即使之前导入了具有该名称或该文件名的模块。

更具体地说,我想编写一个通过以下测试的函数unconditional_import

import os

def make_module(folder, filename, version):
    try: os.mkdir(folder)
    except OSError: pass

    f = open(os.path.join(folder,filename), "w")
    f.write("version = %i" % version)
    f.close()

make_module("test","spam.py", 1)
assert( unconditional_import("test","spam.py").version == 1 )

make_module("test","more_spam.py", 2)
assert( unconditional_import("test","more_spam.py").version == 2 )

make_module("test","more_spam.py", 3)
assert( unconditional_import("test","more_spam.py").version == 3 )

make_module("test2","more_spam.py", 4)
assert( unconditional_import("test2","more_spam.py").version == 4 )

我找到了一个解决方案(我将发布作为保持结构的答案),但它相当丑陋并且感觉不健壮。我希望有一些更简单的原生方式来做到这一点,但我找不到它。

注意:

  • 我知道How to import a module given the full path?,它解决了如何从路径导入模块,但只能运行一次。

  • 我知道在大多数情况下,人们只会重新加载翻译,但这对我来说不是一个选择。

1 个答案:

答案 0 :(得分:2)

到目前为止,我的最佳解决方案是:

def unconditional_import(folder, filename):
    full_path = os.path.join(folder,filename)

    if os.path.isfile(full_path+"c"):
        os.remove(full_path+"c")

    cachefolder = os.path.join(folder,"__pycache__")
    if os.path.isdir(cachefolder):
        for f in os.listdir(cachefolder):
            if f.startswith(filename.rstrip(".py")) and f.endswith(".pyc"):
                os.remove(os.path.join(cachefolder,f))

    if sys.version_info < (3,0):
        from imp import load_source
        foo = load_source("foo", full_path)

    elif sys.version_info < (3,5):
        from importlib.machinery import SourceFileLoader
        foo_module = SourceFileLoader("foo", full_path)
        foo = foo_module.load_module()

    else:
        from importlib.util import spec_from_file_location, module_from_spec
        spec = spec_from_file_location("foo", full_path)
        foo = module_from_spec(spec)
        spec.loader.exec_module(foo)

    return foo

问题和注意事项:

  • 我无法测试Python 3.5及更高版本的变体,但我认为没有理由说它不起作用或为什么会有更简单的解决方案。

  • 手动删除PYC文件让我感到畏缩,我希望它会引起问题。