具有相同名称的Python模块(即在包中重用标准模块名称)

2024-05-13 15:39:32 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个包含模块的包:

SWS/
  __init.py__
  foo.py
  bar.py
  time.py

模块之间需要引用彼此包含的函数。似乎我的time.py模块遇到了问题,因为有一个标准模块使用相同的名称。

例如,在我的foo.py模块需要我的SWS.time模块和标准python time模块的情况下,我遇到了问题,因为解释器在遇到标准time模块之前会查看包内部并找到我的time.py模块。

有办法解决这个问题吗?这是一种不允许使用的情况吗?模块名不应该被重用吗?

任何关于包装理念的解决方案和意见在这里都是有用的。


Tags: 模块函数py名称标准footimeinit
3条回答

正如其他人所说,这通常是一个坏主意。

也就是说,如果你正在寻找潜在的解决方法,或者更好地理解问题,我建议你阅读以下问题:

重用标准函数/类/模块/包的名称从来不是一个好主意。尽量避免。不过,对于你的情况有一些干净的解决方法。

导入SWS.time而不是stdlib time所看到的行为是由于古python版本(2.x)中import的语义所致。要修复它,请添加:

from __future__ import absolute_import

在文件的最上面。这将把import的语义更改为python3.x的语义,后者更为合理。在这种情况下,声明:

import time

将只引用顶级模块。因此,解释器在包内执行导入时不会考虑您的SWS.time模块,但它只使用标准库模块。

如果您的包中的模块需要导入SWS.time,您可以选择:

  • 使用显式相对导入:

    from . import time
    
  • 使用绝对导入:

    import SWS.time as time
    

所以,你的foo.py应该是:

from __future__ import absolute_import

import time

from . import time as SWS_time

这取决于您使用的Python版本。如果您的目标Python版本是2.4或更高版本(在2015年,我当然希望不是),那么是的,这将是一个糟糕的做法,因为没有方法(没有黑客)来区分这两个模块。

然而,在Python 2.5+中,我认为在包名称空间中重用标准lib模块名是非常好的;事实上,这就是the spirit of PEP328

As Python's library expands, more and more existing package internal modules suddenly shadow standard library modules by accident. It's a particularly difficult problem inside packages because there's no way to specify which module is meant. To resolve the ambiguity, it is proposed that foo will always be a module or package reachable from sys.path . This is called an absolute import.

The python-dev community chose absolute imports as the default because they're the more common use case and because absolute imports can provide all the functionality of relative (intra-package) imports -- albeit at the cost of difficulty when renaming package pieces higher up in the hierarchy or when moving one package inside another.

Because this represents a change in semantics, absolute imports will be optional in Python 2.5 and 2.6 through the use of from __future__ import absolute_import

SWS.time显然与time不同,作为代码的读者,我希望SWS.time不仅使用time,而且以某种方式扩展它。

因此,如果SWS.foo需要导入SWS.time,那么它应该使用绝对路径:

# in SWS.foo

# I would suggest renaming *within*
# modules that use SWS.time so that
# readers of your code aren't confused
# with which time module you're using
from SWS import time as sws_time

或者,它应该使用一个显式相对导入,正如巴库鲁的回答:

# in SWS.foo

from . import time as sws_time

如果需要在SWS.time模块中导入标准lib time模块,则首先需要导入未来的功能(仅适用于Python 2.5+;Python 3+在默认情况下执行此操作):

# inside of SWS.time
from __future__ import absolute_import

import time

time.sleep(28800)  # time for bed

注意:from __future__ import absolute_imports只会影响未来功能被导入的模块内的import语句,而不会影响任何其他模块(因为如果另一个模块依赖于相对导入,这将是有害的)。

相关问题 更多 >