如何在包为目录而非文件时使用'import *'并调用导入的函数
如果我在开发一个客户端-服务器应用程序,并且有三个文件(client.py
、server.py
和 common.py
),而 common.py
里有一个很有用的函数(比如 normalize()
),那么在客户端和服务器中使用这个函数就很简单了,像这样:
from common import *
url = normalize(url)
但是,如果因为一些奇怪的原因,我想把这些文件放在不同的子目录里(client
、server
和 common
),而且每个函数都有自己的文件,这样就没有类似的快捷方式了。
我需要调整一下 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 个回答
把 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 client
、import 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
有时候查看标准库,看看这些功能是怎么用的,会很有帮助。
在一个文件夹里的 __init__.py
文件中导入的任何东西,都会在使用 import *
时被导入,前提是这些东西没有被 __all__
限制。