python - 如果从不同的路径导入模块重新导入

标签 python python-import

在我工作的一个大型应用程序中,几个人以不同的方式导入相同的模块,例如 导入 x 或者 从 y 导入 x 其副作用是 x 被导入两次,如果有人依赖全局属性,可能会引入非常微妙的错误

例如假设我有一个包含三个文件 mymodule.py、main.py 和 init.py

的包 mypakcage

mymodule.py 内容

l = []
class A(object): pass

ma​​in.py 内容

def add(x):
    from mypackage import mymodule
    mymodule.l.append(x)
    print "updated list",mymodule.l

def get():
    import mymodule
    return mymodule.l

add(1)
print "lets check",get()

add(1)
print "lets check again",get()

它打印

updated list [1]
lets check []
updated list [1, 1]
lets check again []

因为现在在两个不同的模块中有两个列表,同样类A是不同的 对我来说,这看起来很严重,因为类本身将受到不同的对待 例如下面的代码打印 False

def create():
    from mypackage import mymodule
    return mymodule.A()

def check(a):
    import mymodule
    return isinstance(a, mymodule.A)

print check(create())

问题:

有什么办法可以避免这种情况吗?除了强制该模块应该以一种方式导入 onyl 之外。这不能通过 python 导入机制处理,我在 django 代码和其他地方也看到了几个与此相关的错误。

最佳答案

每个模块命名空间只导入一次。问题是,您以不同的方式导入它们。第一个是从全局包导入,第二个是本地非打包 import。 Python 认为模块是不同的。第一个导入在内部缓存为 mypackage.mymodule,第二个仅作为 mymodule

解决这个问题的方法是始终使用绝对导入。也就是说,始终为您的模块提供从顶级包开始的绝对导入路径:

def add(x):
    from mypackage import mymodule
    mymodule.l.append(x)
    print "updated list",mymodule.l

def get():
    from mypackage import mymodule
    return mymodule.l

请记住,您的入口点(您运行的文件 main.py)也应该在包的外部。当您希望入口点代码位于包内时,通常您会改用运行一个小脚本。示例:

runme.py,包外:

from mypackage.main import main
main()

然后在 main.py 中添加:

def main():
    # your code

我找到了 this document由 Jp Calderone 撰写,是关于如何(不)构建 Python 项目的重要提示。按照它你不会有问题。注意 bin 文件夹 - 它在包外。我将在此处复制整个文本:

Filesystem structure of a Python project

Do:

  • name the directory something related to your project. For example, if your project is named "Twisted", name the top-level directory for its source files Twisted. When you do releases, you should include a version number suffix: Twisted-2.5.
  • create a directory Twisted/bin and put your executables there, if you have any. Don't give them a .py extension, even if they are Python source files. Don't put any code in them except an import of and call to a main function defined somewhere else in your projects.
  • If your project is expressable as a single Python source file, then put it into the directory and name it something related to your project. For example, Twisted/twisted.py. If you need multiple source files, create a package instead (Twisted/twisted/, with an empty Twisted/twisted/__init__.py) and place your source files in it. For example, Twisted/twisted/internet.py.
  • put your unit tests in a sub-package of your package (note - this means that the single Python source file option above was a trick - you always need at least one other file for your unit tests). For example, Twisted/twisted/test/. Of course, make it a package with Twisted/twisted/test/__init__.py. Place tests in files like Twisted/twisted/test/test_internet.py.
  • add Twisted/README and Twisted/setup.py to explain and install your software, respectively, if you're feeling nice.

Don't:

  • put your source in a directory called src or lib. This makes it hard to run without installing.
  • put your tests outside of your Python package. This makes it hard to run the tests against an installed version.
  • create a package that only has a __init__.py and then put all your code into __init__.py. Just make a module instead of a package, it's simpler.
  • try to come up with magical hacks to make Python able to import your module or package without having the user add the directory containing it to their import path (either via PYTHONPATH or some other mechanism). You will not correctly handle all cases and users will get angry at you when your software doesn't work in their environment.

关于python - 如果从不同的路径导入模块重新导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1459236/

相关文章:

python - 在 Jupyter Notebook 中导入期间找不到模块

python - 从上一级目录导入文件

python - 将小部件从另一个文件中的类导入到函数中。名称错误 : name 'textbox1' is not defined

python - C++ Python模块导入错误: "undefined symbol: Py_InitModule3" ( Py_InitModule () )

python - 如何在 wxpython 中使用 Matplotlib.animation?

python - Pymongo $currentDate 对于存储无效

python - keras model.fit文档中 "validation_data will override validation_split."是什么意思

python - 在多个项目中重用 Python 代码的首选方法是什么

python - 每个 flask View 功能有多个路线是不好的做法吗?

python - 为什么这条 python 行不是错误?