如何在包为目录而非文件时使用'import *'并调用导入的函数

0 投票
2 回答
1898 浏览
提问于 2025-04-16 07:58

如果我在开发一个客户端-服务器应用程序,并且有三个文件(client.pyserver.pycommon.py),而 common.py 里有一个很有用的函数(比如 normalize()),那么在客户端和服务器中使用这个函数就很简单了,像这样:

from common import *

url = normalize(url)

但是,如果因为一些奇怪的原因,我想把这些文件放在不同的子目录里(clientservercommon),而且每个函数都有自己的文件,这样就没有类似的快捷方式了。

我需要调整一下 sys.path,然后在导入之后,我需要用 url=normalize.normalize(url) 来调用这个函数。我相信我可以编写一个解决方法,但不知道有没有更好的 Python 方式来处理这个问题?

更新:这是我在遵循 Ignacio 的建议后做的:

$ cat common/__init__.py; client/login.py jcomeauictx.myopenid.com
import os, sys
for module in os.listdir(os.path.dirname(__file__)):
 print >>sys.stderr, 'module: %s' % module
 name, extension = os.path.splitext(module)
 if extension == '.py' and not name.startswith('_'):
  importer = 'from %s import %s' % (name, name)
  print >>sys.stderr, 'import statement: %s' % importer
  exec(importer)

结果:

module: __init__.py
module: normalize.py
import statement: from normalize import normalize
module: __init__.pyc
module: normalize.pyc
('http://www.myopenid.com/server', 'http://jcomeauictx.myopenid.com/')

2 个回答

0

client.py 移到 client/__init__.py,把 server.py 移到 server/__init__.py,把 common 移到 common/__init__.py,这样一切就能像以前一样正常工作了。

关于命名的部分,client.py 是一个叫做 client 的模块,而 client/__init__.py 是一个叫做 client 的包的一部分。你还可以添加 client/something.py,然后使用 import clientimport client.something 或者 from client import something 这样的方式来引用它。一般来说,client/__init__.py 也可以用来把所有东西整合在一起:

client/__init__.py:

from client.foo import *
from client import bar

client/foo.py:

__all__ = ('baz',)

def baz(): pass

client/bar.py:

def something(): pass

然后可以这样使用:

import client
client.baz()
client.bar.something()
from client import bar
bar is client.bar
from client import foo
foo.baz is client.baz

有时候查看标准库,看看这些功能是怎么用的,会很有帮助。

5

在一个文件夹里的 __init__.py 文件中导入的任何东西,都会在使用 import * 时被导入,前提是这些东西没有被 __all__ 限制。

撰写回答