GVKun编程网logo

Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?(python打包后不能用)

18

本文的目的是介绍Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?的详细情况,特别关注python打包后不能用的相关信息。我们将通过专业的研究、有关数据的分

本文的目的是介绍Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?的详细情况,特别关注python打包后不能用的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?的机会,同时也不会遗漏关于if __name__ =&#__main__&# 在 Python 中做什么?、Python if __name__ == ''__main__'':(以主程序形式执行)、Python __init__.py文件的作用、Python __name__ == ''__main__'' 介绍的知识。

本文目录一览:

Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?(python打包后不能用)

Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?(python打包后不能用)

我有一个python程序,它完全包含在具有以下结构的目录中:

myprog/├── __init__.py├── __main__.py├── moduleone.py└── moduletwo.py

我希望能够打包并分发它,以便其他开发人员可以做pip install -e/path/to/git/clone/of/myprog,然后可以在自己的程序中导入myprog并用它做一些很酷的事情。

我还希望能够在命令行中如下运行myprog:

PROMPT> python myprog

当我这样做时,我期望python执行该__main__.py模块。但是,此模块引用在其中声明的某些函数,并且在__init__.py程序在命令行运行时以及在其他程序导入时都需要这些函数可用。但是,出现以下错误:

NameError: name ''function_you_referenced_from_init_file'' is not defined

我是否必须以__main__.py某种方式将这些功能导入?

我尝试了一个简单的示例,如下所示:

PROMPT> cat myprog/__init__.pydef init_myprog():    print ''running __init__.init_myprog()''PROMPT> cat myprog/__main__.pyimport myprogprint ''hi from __main__.py''myprog.init_myprog()PROMPT> ls -l myprogtotal 16-rw-r--r--  1 iit    63B Aug 30 11:40 __init__.py-rw-r--r--  1 iit    64B Aug 30 12:11 __main__.pyPROMPT> python myprogTraceback (most recent call last):  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main    "__main__", fname, loader, pkg_name)  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code    exec code in run_globals  File "/Users/jon/dev/myprog/__main__.py", line 1, in <module>    import myprogImportError: No module named myprog

答案1

小编典典

我是否必须以__main__某种方式将这些功能导入?

是。builtins没有导入,仅提供其中的项目。就像是:

from myprog import func1, func2

应该可以。

如果您没有myprog在常规python路径中安装,则可以使用以下方法解决该问题:

import sysimport ospath = os.path.dirname(sys.modules[__name__].__file__)path = os.path.join(path, ''..'')sys.path.insert(0, path)from myprog import function_you_referenced_from_init_file

坦率地说,这是可怕的。

我建议遵循MartijnPieters的建议,并将其-m放在命令行中,在这种情况下,__main__.py可能看起来像:

from myprog import function_you_referenced_from_init_file

if __name__ =&#__main__&# 在 Python 中做什么?

if __name__ =&#__main__&# 在 Python 中做什么?

if __name__ =

你可能在 python 脚本中经常看到这行代码 if __name__=="__main__": ,但不知道它的实际用途是什么。别担心,因为在这个简短的博客中我们将讨论这个

当您直接运行程序或脚本时,python 会自动将“main”分配给特殊的name变量。这样做基本上是为了表明该文件是此处的“主”脚本,并且正在直接运行而不是导入到另一个脚本中。

要理解这一点,请创建一个新的 python 脚本,假设将其命名为“example.py”并写入:

print("name of script: ", __name__)
登录后复制

运行此命令,您将看到输出的脚本名称:__main__。这只是因为文件是直接运行的。

现在,创建另一个python脚本文件并将example.py导入到这个文件中。运行它,您将看到不同的结果,显示“脚本名称:示例”。这只是因为现在我们不是直接运行它,而是导入脚本并间接运行它。因此,python 现在显示文件的实际名称。

立即学习“Python免费学习笔记(深入)”;

让我们对示例文件进行一些更改,以便我们更好地理解它。

def s_name():
    print("name of script: ", __name__)

s_name()

def greet():
    print("hello! how are you doing?")

if __name__=="__main__":
    greet()

登录后复制

现在,如果您直接运行此命令,一切都会完美执行,但如果您运行导入 example.py 脚本的其他文件,您会注意到greet 函数调用未执行。这是为什么?

这是因为 if 条件。条件的作用是检查文件是否正在直接运行。如果直接运行,main将被分配给特殊变量name,这将使这个条件成立,并且条件内的所有内容都将照常运行。

但另一方面,如果您将其导入另一个文件并从那里间接运行它,那么条件语句将不为真,并且放置在条件中的任何内容都不会被执行。

这就是这个条件语句的意义。 当我们将脚本作为模块导入时,它可以防止python解释器自动运行不必要的代码行。

但是,即使我们将脚本作为模块导入,我们也可以调用这些函数。例如:

import example

example.greet()
登录后复制

这样,即使条件不满足,我们也可以完美地调用导入模块中的任何函数。

以上就是if __name__ =&#__main__&# 在 Python 中做什么?的详细内容,更多请关注php中文网其它相关文章!

Python if __name__ == ''__main__'':(以主程序形式执行)

Python if __name__ == ''__main__'':(以主程序形式执行)

在外部调用某个模块时,可能会将只能在本模块执行的代码给执行了,有没有什么办法让某些特定的代码指定只能在自身运行时才执行被调用时不执行呢?使用 if __name__ == ''__main__'':

示例代码:
创建 Demo 模块 test.py

def Demo(num):
    """
    :param num: 接收一个数
    :return: 返回该数乘自己的结果num**2
    """
    return num ** 2


print("第一次测试:", Demo(1))
print("第二次测试:", Demo(6))

创建调用代码:

test2.py

from Demo4 import Demo

print("计算3的倍数结果:", Demo(3))

执行结果:
	第一次测试: 1
	第二次测试: 36
	计算3的倍数结果: 9

我们可以看到当我们调用时把 test.py 中使用的测试代码也执行了,这显然不是我们想要的结果:

代码改进:
test.py

def Demo(num):
    """
    :param num: 接收一个数
    :return: 返回该数乘自己的结果num**2
    """
    return num ** 2


if __name__ == ''__main__'':  # 当自直接运行本文件时执行以下代码
    print("第一次测试:", Demo(1))
    print("第二次测试:", Demo(6))

test2.py

from Demo4 import Demo

print("计算3的倍数结果:", Demo(3))

执行结果:
	计算3的倍数结果: 9

我们可以看到添加 if __name__ == ''__main__'': 后我们可以把调用时不需要执行的代码放到 if __name__ == ''__main__'': 下方,这样既不会影响到本模块的执行,也不会影响到调用方。

说明: 在每个模块的定义中都包括一个记录模块名称的变量__name__,程序可以检查该变量,以确定他们在哪个模块中执行,如果一个模块不被导入到其他程序中执行,那么他可能在解释器的顶级模块中执行。顶级模块的__name__变量值为__main__.

Python __init__.py文件的作用

Python __init__.py文件的作用

我们经常在python的模块目录中会看到 "__init__.py"  这个文件,那么它到底有什么作用呢?

1. 模块包(module package)标识

  如果你是使用python的相关IDE来进行开发,那么如果目录中存在该文件,该目录就会被识别为 module package 。

2. 控制导包范围

  假设我们的模块包的目录结构如下:

复制代码
.
└── mypackage
    ├── subpackage_1
    │   ├── test11.py
    │   └── test12.py
    ├── subpackage_2
    │   ├── test21.py
    │   └── test22.py
    └── subpackage_3
        ├── test31.py
        └── test32.py
复制代码

  如果我们使用最直接的导入方式,将整个文件拷贝到工程目录下,然后直接导入:

复制代码
from mypackage.subpackage_1 import test11
from mypackage.subpackage_1 import test12
from mypackage.subpackage_2 import test21
from mypackage.subpackage_2 import test22
from mypackage.subpackage_3 import test31
from mypackage.subpackage_3 import test32
复制代码

  当然这个例子里面文件比较少,如果模块比较大,目录比较深的话,可能自己都记不清该如何导入。(很有可能,哪怕只想导入一个模块都要在目录中找很久)

  这种情况下,__init__.py 就很有作用了。我们先来看看该文件是如何工作的。

2.1 __init__.py 是怎么工作的?

  实际上,如果目录中包含了 __init__.py 时,当用 import 导入该目录时,会执行 __init__.py 里面的代码。

  我们在mypackage目录下增加一个 __init__.py 文件来做一个实验:

复制代码
.
└── mypackage
    ├── __init__.py
    ├── subpackage_1
    │   ├── test11.py
    │   └── test12.py
    ├── subpackage_2
    │   ├── test21.py
    │   └── test22.py
    └── subpackage_3
        ├── test31.py
        └── test32.py
复制代码

  mypackage/__init__.py 里面加一个print,如果执行了该文件就会输出:

print("You have imported mypackage")

  下面直接用交互模式进行 import

>>> import mypackage
You have imported mypackage

  很显然,__init__.py 在包被导入时会被执行。

2.2  控制模块导入

  我们再做一个实验,在 mypackage/__init__.py 添加以下语句:

from subpackage_1 import test11

  我们导入 mypackage 试试:

复制代码
>>> import mypackage
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/taopeng/Workspace/Test/mypackage/__init__.py", line 2, in <module>
    from subpackage_1 import test11
ImportError: No module named ''subpackage_1''
复制代码

  报错了。。。怎么回事?

  原来,在我们执行import时,当前目录是不会变的(就算是执行子目录的文件),还是需要完整的包名。

from mypackage.subpackage_1 import test11

  综上,我们可以在__init__.py 指定默认需要导入的模块  

2.3  偷懒的导入方法

  有时候我们在做导入时会偷懒,将包中的所有内容导入

from mypackage import *

  这是怎么实现的呢? __all__ 变量就是干这个工作的。

  __all__ 关联了一个模块列表,当执行 from xx import * 时,就会导入列表中的模块。我们将 __init__.py 修改为 。

__all__ = [''subpackage_1'', ''subpackage_2'']

  这里没有包含 subpackage_3,是为了证明 __all__ 起作用了,而不是导入了所有子目录。

复制代码
>>> from mypackage import *
>>> dir()
[''__builtins__'', ''__doc__'', ''__loader__'', ''__name__'', ''__package__'', ''__spec__'', ''subpackage_1'', ''subpackage_2'']
>>> 
>>> dir(subpackage_1)
[''__doc__'', ''__loader__'', ''__name__'', ''__package__'', ''__path__'', ''__spec__'']
复制代码

  子目录的中的模块没有导入!!!

  该例子中的导入等价于

from mypackage import subpackage_1, subpackage_2

  因此,导入操作会继续查找 subpackage_1 和 subpackage_2 中的 __init__.py 并执行。(但是此时不会执行 import *

  我们在 subpackage_1 下添加 __init__.py 文件:

__all__ = [''test11'', ''test12'']

# 默认只导入test11
from mypackage.subpackage_1 import test11

  再来导入试试

复制代码
>>> from mypackage import *
>>> dir()
[''__builtins__'', ''__doc__'', ''__loader__'', ''__name__'', ''__package__'', ''__spec__'', ''subpackage_1'', ''subpackage_2'']
>>> 
>>> dir(subpackage_1)
[''__all__'', ''__builtins__'', ''__cached__'', ''__doc__'', ''__file__'', ''__loader__'', ''__name__'', ''__package__'', ''__path__'', ''__spec__'', ''test11'']
复制代码

  如果想要导入子包的所有模块,则需要更精确指定。

>>> from mypackage.subpackage_1 import *
>>> dir()
[''__builtins__'', ''__doc__'', ''__loader__'', ''__name__'', ''__package__'', ''__spec__'', ''test11'', ''test12'']

3. 配置模块的初始化操作

  在了解了 __init__.py 的工作原理后,应该能理解该文件就是一个正常的python代码文件。

  因此可以将初始化代码放入该文件中。

 

  至此。转载请注明出处。

Python __name__ == ''__main__'' 介绍

Python __name__ == ''__main__'' 介绍

当你打开一个.py文件时,经常会在代码的最下面看到if __name__ == ''__main__'': 那它有什么作用了

模块是对象,并且所有的模块都有一个内置属性 __name__。一个模块的 __name__ 的值取决于您如何应用模块。如果 import 一个模块,那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名。但是您也可以像一个标准的程序样直接运行模块,在这 种情况下, __name__ 的值将是一个特别缺省"__main__"。

下面用一个实例来降级这个问题, 用python工具打开一个python文档

# Test.py

# Test.py
# coding=utf-8

def test():
    print("python is runing")

if __name__==''__main__'':
    test()
else:
    print("python don''t runing")


直接运行,得到的是python is runing,如果我们另一个文件导入这个文件,if __name__ 就起到了限制作用,如下文件

# Test2.py

# coding=utf-8
import Test
print test.__name__

运行Test2.py 我们将直接得到pythong don''t runing的提示,就是因为__name__ 已经发生改变


关于Python:模块和打包-为什么在__main__.py之前不执行__init__.py文件?python打包后不能用的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于if __name__ =&#__main__&# 在 Python 中做什么?、Python if __name__ == ''__main__'':(以主程序形式执行)、Python __init__.py文件的作用、Python __name__ == ''__main__'' 介绍等相关内容,可以在本站寻找。

本文标签: