这是我正在使用的结构:
directory/
script.py
subdir/
__init__.py
myclass01.py
myclass02.py
我想要做的是在script.py中导入myclass01.py
和myclass02.py
中定义的类。如果我这样做:
from subdir.myclass01 import *
它适用于myclass01.py
中定义的类。但是使用此解决方案,如果在subdir
中的不同文件中定义了许多类,并且我想要导入所有这些类,那么我必须为每个文件键入一行。必须有一个捷径。我试过了:
from subdir.* import *
但它没有成功。
编辑:以下是文件的内容:
这是__init__.py
(根据Apalala建议使用__all__
):
__all__ = ['MyClass01','MyClass02']
这是myclass01.py
:
class MyClass01:
def printsomething():
print 'hey'
这是myclass02.py
:
class MyClass02:
def printsomething():
print 'sup'
这是script.py
:
from subdir import *
MyClass01().printsomething()
MyClass02().printsomething()
这是我尝试运行script.py
时获得的回溯:
File "script.py", line 1, in <module>
from subdir import *
AttributeError: 'module' object has no attribute 'MyClass01'
答案 0 :(得分:12)
虽然在那里使用的名称与您问题的目录结构中显示的名称不同,但您可以使用我对标题为Namespacing and classes的问题的回答。此处显示的__init__.py
也允许usepackage.py
脚本以这种方式编写(package
映射到您问题中的subdir
,Class1
映射到myclass01
{1}}等):
from package import *
print Class1
print Class2
print Class3
修订版(已更新):
糟糕,对不起,我的其他答案中的代码并不能完全按照您的意愿行事 - 它只会自动导入任何包子模块的名称。要使它还从每个子模块导入命名属性,还需要几行代码。这是包的__init__.py
文件的修改版本(也适用于Python 3.4.1):
def _import_package_files():
""" Dynamically import all the public attributes of the python modules in this
file's directory (the package directory) and return a list of their names.
"""
import os
exports = []
globals_, locals_ = globals(), locals()
package_path = os.path.dirname(__file__)
package_name = os.path.basename(package_path)
for filename in os.listdir(package_path):
modulename, ext = os.path.splitext(filename)
if modulename[0] != '_' and ext in ('.py', '.pyw'):
subpackage = '{}.{}'.format(package_name, modulename) # pkg relative
module = __import__(subpackage, globals_, locals_, [modulename])
modict = module.__dict__
names = (modict['__all__'] if '__all__' in modict else
[name for name in modict if name[0] != '_']) # all public
exports.extend(names)
globals_.update((name, modict[name]) for name in names)
return exports
if __name__ != '__main__':
__all__ = ['__all__'] + _import_package_files() # '__all__' in __all__
或者你可以将上面的内容放在一个单独的.py模块文件中,并在包目录__init__.py
中使用它,如下所示:
if __name__ != '__main__':
from ._import_package_files import * # defines __all__
__all__.remove('__all__') # prevent export (optional)
无论你命名文件是什么,它都应该以{{1}}下划线字符开头,因此它不会递归地尝试_
。
答案 1 :(得分:6)
您最好的选择,虽然可能不是最好的风格,但是将所有内容导入到包的命名空间中:
# this is subdir/__init__.py
from myclass01 import *
from myclass02 import *
from myclass03 import *
然后,在其他模块中,您可以直接从包中导入所需内容:
from subdir import Class1
答案 2 :(得分:5)
我知道自从这个问题得到解答以来已经过了几个月了,但我一直在寻找同样的事情并且碰到了这个页面。我对所选择的答案并不是很满意,所以我最终编写了自己的解决方案,并认为我会分享它。这就是我想出的:
# NOTE: The function name starts with an underscore so it doesn't get deleted by iself
def _load_modules(attr_filter=None):
import os
curdir = os.path.dirname(__file__)
imports = [os.path.splitext(fname)[0] for fname in os.listdir(curdir) if fname.endswith(".py")]
pubattrs = {}
for mod_name in imports:
mod = __import__(mod_name, globals(), locals(), ['*'], -1)
for attr in mod.__dict__:
if not attr.startswith('_') and (not attr_filter or attr_filter(mod_name, attr)):
pubattrs[attr] = getattr(mod, attr)
# Restore the global namespace to it's initial state
for var in globals().copy():
if not var.startswith('_'):
del globals()[var]
# Update the global namespace with the specific items we want
globals().update(pubattrs)
# EXAMPLE: Only load classes that end with "Resource"
_load_modules(attr_filter=lambda mod, attr: True if attr.endswith("Resource") else False)
del _load_modules # Keep the namespace clean
这只是从包目录中的所有.py文件导入*,然后只将公共文件拉入全局命名空间。此外,如果只需要某些公共属性,它允许过滤器。
答案 3 :(得分:0)
我用这个简单的方法:
import module
或from module import function1, class1
。请注意,module
只是*.py
文件的名称,没有扩展部分。
这是一个一般例子:
import sys
sys.path.append("/path/to/folder/")
import module # in that folder
在你的情况下,它可能是这样的:
import sys
sys.path.append("subdir/")
import myclass01
# or
from myclass01 import func1, class1, class2 # .. etc
答案 4 :(得分:-2)
from subdir.* import *
你不能在'from'语句之后直接使用'*'。 你需要明确的进口。请查看有关导入和包的Python文档。