如果从一个函数中导​​入模块 x 次,会有什么问题吗?

Are there any issues if importing modules x times from a function?

我提取 PyPDF2 1.26.0 工具包并将其放入我的插件目录中。层次结构如下所示:

plugin
  |__example.py
  |__report
       |__PyPDF2
            |__(PyPDF2 contents)

example.py 文件的开头,我尝试使用以下方法导入 PyPDF2 模块:

from report.PyPDF2.PyPDF2 import PdfFileMerger

不幸的是,这会导致错误:

ImportError: No module named report.PyPDF2.PyPDF2

但我可以使用 sys:

导入它
import os, sys

class plugin:
    def __init__(self, iface):
        self.iface = iface
        self.plugin_dir = os.path.dirname(__file__)
        ...

    def pdf_merger(self):
        # Import PyPDF2
        sys.path.append(str(self.plugin_dir) + '/report/PyPDF2')        
        from PyPDF2 import PdfFileMerger

        merger = PdfFileMerger()
        return merger

    def func(self):
        merger = self.pdf_merger()
        ...

问题是 func() 会被调用多次,所以每次 from PyPDF2 import PdfFileMerger 都会被调用 运行。这会导致任何问题(即内存问题等)吗?为什么我不能使用 from report.PyPDF2.PyPDF2 import PdfFileMerger 导入模块?

你试过了吗:

from report.PyPDF2 import PdfFileMerger

反正导入的模块是有缓存的,一个导入多次也不用担心

I extracted and placed the PyPDF2 1.26.0 toolkit into my plugin directory

我不知道你的 "plugin directory" 是什么,但这不是安装 python 包的方法。您想改用 pip 之类的东西,最好使用 virtualenv.

ImportError: No module named report.PyPDF2.PyPDF2

我假设第一个 "PyPDF2" 目录是 github 根目录(参见 https://github.com/mstamy2/PyPDF2). This directory is not a proper python package(它没有 __init__.py 文件)但是项目的目录。你想要的是在 "report" 中只有 "second-level" PyPDF2 目录( 实际的 python 包),然后使用from report.PyPDF2 import PdfFileMerger.

但是再说一次,这不是安装 python 软件包的正确方法,参见上面的内容。

def pdf_merger(self):
    # Import PyPDF2
    sys.path.append(str(self.plugin_dir) + '/report/PyPDF2')        
    from PyPDF2 import PdfFileMerger

这将一遍又一遍地附加到 sys.path(如果您的进程运行数周或数月,这可能确实最终会导致内存问题,具体取决于此操作的频率)函数被调用)。 IOW:不要那样做。正确安装 PyPDF2 作为依赖项(再一次,pipvirtualenv 是你的朋友)或者 至少 只安装 "inner" PyPDF2 包作为上面有解释。

请注意,这里的问题不是一遍又一遍地导入相同的模块(第一次导入将缓存该模块),而是一遍又一遍地附加到 sys.path。 "local" 导入的唯一问题是性能受到非常轻微的影响,但您可能永远不会注意到它,除非这是一个在非常紧密的循环中调用的关键函数。

此外,当我们在做的时候:

    sys.path.append(str(self.plugin_dir) + '/report/PyPDF2')        

1/ 无需将 self.plugin_dir 传递给 str(它已经是一个),并且 2/ 硬编码路径分隔符是一个非常糟糕的主意 - 你想要 os.path.join(self.plugin_dir, 'report', 'PyPDF2') 而不是(在这种情况下你实际上想要 none - 单独留下 sys.path 并正确安装 PyPDF2)