从子目录中的不同文件导入类 [英] Importing classes from different files in a subdirectory
问题描述
以下是我正在使用的结构:
Here's the structure I'm working with:
directory/
script.py
subdir/
__init__.py
myclass01.py
myclass02.py
我想要做的是在script.py中导入 myclass01.py
和 myclass02.py
中定义的类。如果我这样做:
What I want to do is import in script.py the classes defined in myclass01.py
and myclass02.py
. If I do:
from subdir.myclass01 import *
它适用于 myclass01.py
中定义的类。但是使用这个解决方案,如果在 subdir
中的不同文件中定义了许多类,并且我想要导入所有这些类,我必须为每个文件键入一行。必须有一个捷径。我试过:
It works fine for the class defined in myclass01.py
. But with this solution if there are many classes defined in different files in subdir
and I want to import all of them, I'd have to type one line for each file. There must be a shortcut for this. I tried:
from subdir.* import *
但它没有成功。
编辑:这里是内容文件:
这是 __ init __。py
(使用 __ all __
如Apalala建议的那样):
This is __init__.py
(using __all__
as Apalala suggested):
__all__ = ['MyClass01','MyClass02']
这是 myclass01.py
:
class MyClass01:
def printsomething():
print 'hey'
这是 myclass02.py
:
class MyClass02:
def printsomething():
print 'sup'
来自subdir import的 script.py
:
This is script.py
:
from subdir import *
MyClass01().printsomething()
MyClass02().printsomething()
<这是我尝试运行 script.py $时获得的回溯c $ c>:
File "script.py", line 1, in <module>
from subdir import *
AttributeError: 'module' object has no attribute 'MyClass01'
推荐答案
虽然这里使用的名称与你的问题目录结构中显示的名称不同,但你可以使用我对a href =https://stackoverflow.com的问题的回答。 / questions / 5117194 / python-namespacing-and-classes / 5118437#5118437> 命名空间和类 。显示的 __ init __。py
也允许 usepackage.py
脚本以这种方式编写( package
在您的问题中映射到 subdir
, Class1
到 myclass01
等):
Although the names used there are different from what's shown in your question's directory structure, you could use my answer to the question titled Namespacing and classes. The __init__.py
shown there would have also allowed the usepackage.py
script to have been written this way (package
maps to subdir
in your question, and Class1
to myclass01
, etc):
from package import *
print Class1
print Class2
print Class3
修订版(更新):
糟糕,抱歉,我的其他答案中的代码并不能完全按照您的意愿行事 - 它只会自动导入任何包的名称子模块。要使它还从每个子模块导入命名属性,还需要几行代码。这是包的 __ init __。py
文件的修改版本(也适用于Python 3.4.1):
Oops, sorry, the code in my other answer doesn't quite do what you want — it only automatically imports the names of any package submodules. To make it also import the named attributes from each submodule requires a few more lines of code. Here's a modified version of the package's __init__.py
file (which also works in 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
中使用它,如下所示:
Alternatively you can put the above into a separate .py module file of its own in the package directory, and use it from the package's __init__.py
like this:
if __name__ != '__main__':
from ._import_package_files import * # defines __all__
__all__.remove('__all__') # prevent export (optional)
无论你命名文件是什么,它应该是以 _开头的东西
下划线字符,因此它不会尝试 import
本身recursiv ely。
Whatever you name the file, it should be something that starts with an _
underscore character so it doesn't try to import
itself recursively.
这篇关于从子目录中的不同文件导入类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!