Importing classes from different files in a subdirectory
以下是我正在使用的结构:
1 2 3 4 5 6 | directory/ script.py subdir/ __init__.py myclass01.py myclass02.py |
我要做的是在script.py中导入在
1 | from subdir.myclass01 import * |
对于
1 | from subdir.* import * |
但没有成功。
编辑:以下是文件的内容:
这是
1 | __all__ = ['MyClass01','MyClass02'] |
我是
1 2 3 | class MyClass01: def printsomething(): print 'hey' |
我是
1 2 3 | class MyClass02: def printsomething(): print 'sup' |
我是
1 2 3 | from subdir import * MyClass01().printsomething() MyClass02().printsomething() |
这是我在运行
1 2 3 | File"script.py", line 1, in <module> from subdir import * AttributeError: 'module' object has no attribute 'MyClass01' |
尽管此处使用的名称与问题目录结构中显示的名称不同,但您可以使用我对题为"名称间距和类"的问题的回答。这里显示的
1 2 3 4 5 | from package import * print Class1 print Class2 print Class3 |
修订(更新):
对不起,我的另一个答案中的代码并不能完全满足您的需要——它只会自动导入任何包子模块的名称。要使其同时从每个子模块导入命名属性,还需要几行代码。下面是该包的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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模块文件中,并从包的
1 2 3 | if __name__ != '__main__': from ._import_package_files import * # defines __all__ __all__.remove('__all__') # prevent export (optional) |
无论您如何命名该文件,它都应该是以
您最好的选择是将所有内容导入包的命名空间,尽管这可能不是最佳样式:
1 2 3 4 | # this is subdir/__init__.py from myclass01 import * from myclass02 import * from myclass03 import * |
然后,在其他模块中,可以直接从包中导入所需内容:
1 | from subdir import Class1 |
我知道这个问题被回答已经有几个月了,但我在找同样的东西,并浏览了这一页。我对选择的答案不太满意,所以最后我写了自己的解决方案,并想和大家分享一下。我想到的是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # 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文件导入*,然后只将公共文件拉入全局命名空间。此外,如果只需要某些公共属性,它还允许使用过滤器。
我用这个简单的方法:
注意,
下面是一个一般示例:
1 2 3 | import sys sys.path.append("/path/to/folder/") import module # in that folder |
在您的案例中,可能是这样的:
1 2 3 4 5 | import sys sys.path.append("subdir/") import myclass01 # or from myclass01 import func1, class1, class2 # .. etc |
1 | from subdir.* import * |
不能在"From"语句后直接使用"*"。你需要解释导入。请查看有关导入和包的python文档。