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

查看:32
本文介绍了模块导入和 __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.此外,您还必须考虑是否要将 module1module2module3 作为外部 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 的 >scriptsconsole_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天全站免登陆