模块导入和__init__.py [英] Module imports and __init__.py

查看:69
本文介绍了模块导入和__init__.py的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解关于Python(v2.7)导入机制的最佳实践.我有一个项目开始有所发展,可以说我的代码的组织方式如下:

I am trying to understand what the best practices are with regards to Python's (v2.7) import mechanics. I have a project that has started to grow a bit and lets say my code is organised as follows:

foo/
    __init__.py
    Foo.py
    module1.py
    module2.py
    module3.py

程序包名称为 foo ,在其下方有模块 Foo.py ,其中包含类 Foo 的代码.因此,我对包,模块和类使用了相同的名称,而这些名称起初可能不太聪明.

The package name is foo and underneath it I have module Foo.py which contains code for the class Foo. Hence I am using the same name for the package, module and class which might not be very clever to start with.

__ init __.py 为空,类 Foo 需要导入 module1,module2和module3 ,因此是我的 Foo.py的一部分文件如下:

__init__.py is empty and class Foo needs to import module1, module2 and module3 hence part of my Foo.py file looks like:

# foo/Foo.py

import module1
import module2
import module3

class Foo(object):
    def __init__(self):
....
....
if __name__ == '__main__':
    foo_obj = Foo()

但是后来我重新讨论了这一点,我认为最好将所有导入都保存在 __ init __.py 文件中.因此,我的 __ init __.py 现在看起来像:

However I later revisited this and I thought it would be better to have all imports in the __init__.py file. Hence my __init__.py now looks like:

# foo/__init__.py

import Foo
import module1
import module2
import module3
....
....

和我的 Foo.py 只需要导入 foo :

# foo/Foo.py

import foo

虽然这很方便,因为它是一个班轮,但我有点担心它可能会产生循环进口.我的意思是,当脚本 Foo.py 运行时,它将导入所有可能的内容,然后将调用 __ init __.py 并将其导入 Foo.py再次(对吗?).此外,对于包,模块和类使用相同的名称会使情况更加混乱.

While this looks convenient since it is an one liner, I am a bit worried that it might be creating circular imports. What I mean is that when the script Foo.py is run it will import everything it can and then __init__.py will be called which will import Foo.py again (is that correct?). Additionally using the same name for package, module and class makes things more confusing.

我这样做的方式有意义吗?还是我在找麻烦?

Does it make sense the way I have done it? Or am I asking for trouble?

推荐答案

如果仅遵守一些流行的python约定和标准,您可以做一些改善组织的事情.

A couple things you could do to improve your organizaton, if only to adhere to some popular python conventions and standards.

如果您搜索此主题,则不可避免地会遇到人们建议 PEP8 指南.这些是组织python代码的事实上的规范标准.

If you search this topic, you will inevitably run across people recommending the PEP8 guidelines. These are the de facto canonical standards for organizing python code.

模块应使用简短的全小写名称.下划线可以是如果可以提高可读性,请在模块名称中使用.Python包也应该使用短的全小写名称,尽管使用不鼓励使用下划线.

Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.

根据这些准则,您的项目模块应命名为:

Based on these guidelines, your project modules should be named like this:

foo/
    __init__.py
    foo.py
    module1.py
    module2.py
    module3.py

我发现通常最好避免不必要地在 __ init __.py 中导入模块,除非您出于命名空间原因这样做.例如,如果您想让程序包的命名空间看起来像这样

I find it's generally best to avoid importing modules unnecessarily in __init__.py unless you're doing it for namespace reasons. For example, if you want the namespace for your package to look like this

from foo import Foo

代替

from foo.foo import Foo

然后放置

from .foo import Foo

在您的 __ init __.py 中.随着程序包的变大,某些用户可能不想使用所有子程序包和模块,因此通过隐式将它们导入来强迫用户等待所有这些模块加载是没有意义的.__init __.py .另外,您还必须考虑是否还要将 module1 module2 module3 作为外部API的一部分.它们是否仅由 Foo 使用,而不是供最终用户使用?如果它们仅在内部使用,则不要将它们包含在 __ init __.py

in your __init__.py. As your package gets larger, some users may not want to use all of the sub-packages and modules, so it doesn't make sense to force the user to wait for all those modules to load by implicitly importing them in your __init__.py. Also, you have to consider whether you even want module1, module2, and module3 as part of your external API. Are they only used by Foo and not intended to be for end users? If they're only used internally, then don't include them in the __init__.py

我还建议使用绝对或显式相对导入导入子模块.例如,在 foo.py

I'd also recommend using absolute or explicit relative imports for importing sub-modules. For example, in foo.py

from foo import module1
from foo import module2
from foo import module3

显式相对

from . import module1
from . import module2
from . import module3

这将防止其他软件包和模块的任何命名问题.如果您决定支持Python3,也将变得更加容易,因为Python3不支持您当前使用的隐式相对导入语法.

This will prevent any possible naming issues with other packages and modules. It will also make it easier if you decide to support Python3, since the implicit relative import syntax you're currently using is not supported in Python3.

此外,您包中的文件通常不应包含

Also, files inside your package generally shouldn't contain a

if __name__ == '__main__'

这是因为将文件作为脚本运行意味着该文件不会被视为属于该文件包的一部分,因此无法进行相对导入.

This is because running a file as a script means it won't be considered part of the package that it belongs to, so it won't be able to make relative imports.

向用户提供可执行脚本的最佳方法是使用 setuptools 的> scripts console_scripts 功能.根据使用的方法,组织脚本的方式可能会有所不同,但是我通常这样组织我的:

The best way to provide executable scripts to users is by using the scripts or console_scripts feature of setuptools. The way you organize your scripts can be different depending on which method you use, but I generally organize mine like this:

foo/
    __init__.py
    foo.py
    ...
scripts/
     foo_script.py
setup.py

这篇关于模块导入和__init__.py的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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