Python如何处理同名模块和包?

89 投票
3 回答
36676 浏览
提问于 2025-04-16 19:48

假设我有一个模块叫做 foo.py,还有一个包叫做 foo/。如果我调用了某个东西,

import foo

那么这两者中哪个会被加载呢?我该怎么指定我想加载模块还是包呢?

3 个回答

15

也许你想把你的类从 foo.py 文件移动到 __init__.py 文件里。

这样的话,你就可以从这个包里导入它们,同时也可以导入一些可选的子包:

文件 foo/__init__.py:

class Bar(object):
...

文件 foo/subfoo.py:

class SubBar(object):
...

文件 mymodule.py:

from foo import Bar
from foo.subfoo import SubBar
20

其实,这是可以做到的,只要手动引导导入机制使用一个 .py 文件,而不是目录。(这段代码测试得不太充分,但看起来是有效的)。2020年更新:请注意,这需要使用自定义的 import_module() 函数,而不是普通的 import 语句。不过,随着现代 Python3 及其 importlib 模块的出现,可能也能让普通的 import 语句以相同的方式工作。(请注意,这个回答展示了 Python 的灵活性。这不是鼓励你在应用中使用这种方法。只有在你知道自己在做什么的情况下才使用它。)

文件 foo.py

print "foo module loaded"

文件 foo/__init__.py

print "foo package loaded"

文件 test1.py

import foo

文件 test2.py

import os, imp

def import_module(dir, name):
    """ load a module (not a package) with a given name 
        from the specified directory 
    """
    for description in imp.get_suffixes():
        (suffix, mode, type) = description
        if not suffix.startswith('.py'): continue
        abs_path = os.path.join(dir, name + suffix)
        if not os.path.exists(abs_path): continue
        fh = open(abs_path)
        return imp.load_module(name, fh, abs_path, (description))

import_module('.', 'foo')

运行

$ python test1.py 
foo package loaded

$ python test2.py 
foo module loaded
33

我认为这个包总是会被加载。根据我所知道的,你无法避免这个情况。所以要么改一下包的名字,要么改一下模块的名字。相关文档可以查看这里:http://docs.python.org/tutorial/modules.html#the-module-search-path

撰写回答