我遇到了这样的情况:同一个Python模块在两个不同版本的同一个目录中;mymodule.pymymodule.so(我通过Cython从第一个目录获得后者,但这与我的问题无关)。从Python开始

import mymodule

它总是选择mymodule.so。有时我真的想导入mymodule.py。我可以暂时将mymodule.so移动到另一个位置,但如果同时运行另一个需要导入mymodule.so的Python实例,则效果不好。
问题是如何使import更喜欢.py文件而不是.so
以下是我对解决方案的看法:
我想象着使用importlib执行一些魔术,并可能编辑sys.meta_path。具体地说,我看到sys.meta_path[2]包含用于导入外部模块的_frozen_importlib_external.PathFinder,即这用于mymodule.pymymodule.so。如果我可以用一个类似的PathFinder替换它,它对文件类型使用反向排序,我就有了一个解决方案。
如果这会影响解决方案,我将使用Python3.7。
编辑
注意,在mymodule.pyexec的源行中简单地读取它们是不可能的,因为mymodule.py本身可能导入在.py.so版本中再次存在的其他模块(我也希望导入这些.py版本)。

最佳答案

我想到了这个。它不太漂亮,但似乎有用。

import glob, importlib, sys

def hook(name):
    if name != '.':
        raise ImportError()
    modnames = set(f.rstrip('.py') for f in glob.glob('*.py'))
    return Finder(modnames)
sys.path_hooks.insert(1, hook)
sys.path.insert(0, '.')

class Finder(object):
    def __init__(self, modnames):
        self.modnames = modnames
    def find_spec(self, modname, target=None):
        if modname in self.modnames:
            origin = './' + modname + '.py'
            loader = Loader()
            return importlib.util.spec_from_loader(modname, loader, origin=origin)
        else:
            return None

class Loader(object):
    def create_module(self, target):
        return None
    def exec_module(self, module):
        with open(module.__spec__.origin, 'r', encoding='utf-8') as f:
            code = f.read()
        compile(code, module.__spec__.origin, 'exec')
        exec(code, module.__dict__)

关于python - Python:强制导入优先使用.py而不是.so,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56074754/

10-12 00:39