从子目录中的不同文件导入类 [英] Importing classes from different files in a subdirectory

查看:107
本文介绍了从子目录中的不同文件导入类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我正在使用的结构:

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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆