快捷搜索:
来自 计算机编程 2019-08-24 23:39 的文章
当前位置: 67677新澳门手机版 > 计算机编程 > 正文

67677新澳门手机版语句在调用多进程Process过程中

2018年2月27日 于创B515

Python中if __name__=="__main__" 语句在调用多进程Process进程中的功用剖析,__name____main__

2018年2月27日 于创B515

  

引言
  方今备选攻读一下怎么着利用Python中的多进度。在翻占卜关书籍、英特网资料时意识具有代码都含有if __name__=="__main__",在实验的历程中窥见只要在运作代码进度中,没有那句话Python解释器就能报错。就算Python对于multiprocessing的文书档案第17.2.1.1节中【1】提到必须那样使用,可是作者感到并从未根本上分解清楚。因此笔者主宰从源码来评释自身的疑心。

# 代码0.1错误代码
import multiprocessing as mp
import os

def do():
    print("pid is : %s ..." % os.getpid())

print("parent id is : %s ..." % os.getpid())
p = mp.Process(target=do, args=())
p.start()

# 代码0.2正确代码
import multiprocessing as mp
import os

def do():
    print("pid is : %s ..." % os.getpid())

if __name__ == '__main__':
    print("parent id is : %s ..." % os.getpid())
    p = mp.Process(target=do, args=())
    p.start()

 

标题陈说
问题
67677新澳门手机版 ,在运行代码-0.1时,会产出RuntimeError,错误提醒如下。不过运转代码0.2时就不会,一切顺遂。

    An attempt has been made to start a new process before the current process has finished its bootstrapping phase.
    This probably means that you are not using fork to start your child processes and you have forgotten to use the 
proper idiom in the main module:
       if __name__ == '__main__':
        freeze_support()
        ...
  The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.

 

题目时有产生的情形

环境配置
运行环境:  Win10
IDE Sublime Text3

 

简言之表明
  由于Python运维进度中,新创设进程后,进度会导入正在运作的文本,即在运作代码0.1的时候,代码在运行到mp.Process时,新的进度会再也读入改代码,对于从未if __name__=="__main__"爱戴的代码,新进度皆以为是要重复运转的代码,那是子进度又二回运营mp.Process,可是在multiprocessing.Process的源码中是对子进度再度爆发子进度是做了限制的,是不容许的,于是应际而生如上的谬误提醒。

详尽分解
先谈一谈if__name__=="__main__"
  在Python有关__main__的文书档案中【2】表达“__main__”是代码实施时的最高的命名空间(the name of the scope in which top-level code executes),今世码被当做脚本读入的时候,命名空间会被取名称叫“__main__”,对于在剧本运维进度中读入的代码命名空间都不会被命名字为“__main__”。那也便是创设的子进度是不会读取__name__=="__main__"爱惜下的代码。

再谈一谈multiprocessing(win32下的源码深入分析)
multiprocessing依据平台分裂会推行不一的代码:在类UNIX系统下是因为操作系统本人援助fork()语句,win32系统由于自家不匡助fork(),由此在二种系统下multiprocessing会运营不一样的代码,如图1 UNIX平台、图2 win32平台(包罗在context.py文件中,Process的定义也是在context.py文件中)。

67677新澳门手机版 1

图1 对此类UNIX系统平台

67677新澳门手机版 2

图2 对此win32系统平台

  Process是贰个莫斯中国科学技术大学学依赖承继的类———其父类是BaseProcess,如图3 Process类的定义。在运用进度中先初叶化贰个Process实例,然后经过Process.start()来运转子进度。我们传承看关于Process.start()的概念,如图4 BaseProcess类中的start()定义。在里面第105行,调用了self._波普n(self),该函数重定义定义于Process类。该函数按调用顺序最终会跳转到 popen_spwan_win32.py 文书中的波普n类,如图5 Popen类的定义。波普n类在开头话进程中第一调用windows相关接口,生成一个管道(38行),取得对管道读写的句柄,然后生成贰个命令行的字符串列表——cmd,如下:

['C:\Program Files\Python35\python.exe', '-B', '-c', 
'from multiprocessing.spawn import spawn_main;spawn_main(pipe_handle=928, parent_pid=9292)', 
'--multiprocessing-fork']

67677新澳门手机版 3

图3 Process类的定义

67677新澳门手机版 4

图4 BaseProcess类中的start()定义

67677新澳门手机版 567677新澳门手机版 6

图5 Popen类的定义

  这一个字符串列表之后通过命令行送入系统,得到相应的子进度和子线程的句柄及子进度和子线程的ID号。在第65、66行是通过pickle方法将要求的数码从父进度传输给子进度。新历程是调用spawn.py文件中的spawn_main函数,如图6 spawnmain的定义。其中第100行的steal_handle()的法力是子进度猎取父进程生成的句柄,用于后续通讯——使用pickle方法从父进度中读取供给数据。而难题的产出便是在那之后出现!该代码在第106行调用_main(),其次在第115行调用prepare(),再度运维到223行时,运行_fixup_main_from_name(),而那时候该函数会运作父进度的脚本。因而对于从未if__name__=="__main__"爱护的代码都以要运转的,而此时在第叁遍运维Process创设新进度的时候在第123行 if getattr(process.current_process(), '_inheriting', False): 时,由于子进度是具备_inheriting属性,因而会点燃出上述错误代码。

67677新澳门手机版 7

图6 spawn_main的定义

  对于代码中生成新子进程时所用到的多少个技艺自己觉很风趣也很闹心,因而决定继续看下来。上边轻松描述一下五个本领的概略。

 —— pickle模块

  首先是pickle模块。pickle模块是二个Python中有意识的数码格式,与JSON等分化,是无法被另外语言识其余格式。在Python中的官方文书档案【3】中相比较了pickle模块与JSON的分裂之处,以及介绍了pickle的运用法规。轻松摘录如下:

           pickle与JSON的区别             
  • JSON 是text文本格式而pickle是二进制流
  • JSON 是可读的而pickle是不可读的
  • JSON 可用于其他语言环境,而pickle仅仅用于Python自身
  • JSON 对于Python中的一些内建(built-in)类型会失效,而pickle都是有效的
可以被pickle模块pickle的数据
  • None、True、False
  • 整数、浮点数、复数
  • 字符串、字节、字节数组
  • 包含可以被pickle数据的元组、列表、集合、字典
  • 使用def定义的函数
  • 在模块top-level定义的内建(built-in)函数和类

 

 —— 管道(Pipe)
  这里领会管道是从类UNIX系统精晓,因为其精通起来更便利。管道在类UNIX系统中也是一种文件,在转移新的子进程的时候将多个经过都关涉至同二个管道上,这样就是双工通讯(父子进程并行可读可写)。若是要贯彻单工通讯,就关闭相应的坦途(一方写一方读)【4】。

参照他事他说加以考察文献

 

__name__==__main__ 语句在调用多进度Process进度中的成效解析,__name____main__ 二零一八年二月二日 于创B515 引言 方今备选攻读一下什么样行使Pyt...

 —— pickle模块

 

图4 BaseProcess类中的start()定义

['C:\Program Files\Python35\python.exe', '-B', '-c', 
'from multiprocessing.spawn import spawn_main;spawn_main(pipe_handle=928, parent_pid=9292)', 
'--multiprocessing-fork']

 

# 代码0.1错误代码
import multiprocessing as mp
import os

def do():
    print("pid is : %s ..." % os.getpid())

print("parent id is : %s ..." % os.getpid())
p = mp.Process(target=do, args=())
p.start()

# 代码0.2正确代码
import multiprocessing as mp
import os

def do():
    print("pid is : %s ..." % os.getpid())

if __name__ == '__main__':
    print("parent id is : %s ..." % os.getpid())
    p = mp.Process(target=do, args=())
    p.start()
环境配置
运行环境:  Win10
IDE Sublime Text3

参照他事他说加以考察文献

67677新澳门手机版 867677新澳门手机版 9

  1. Python3.5 关于multiprocessing的文档  
  2. Python3.5 关于__main__的文档    
  3. Python3.5 关于pickle的文档                       
  4. 网络一片关于pipe的介绍                             

图2 对此win32体系平台

再谈一谈multiprocessing(win32下的源码剖判)
multiprocessing依据平台分歧会实行不一的代码:在类UNIX系统下是因为操作系统本人协理fork()语句,win32种类由于自家不帮忙fork(),由此在三种系统下multiprocessing会运维不一致的代码,如图1 UNIX平台、图2 win32平台(包蕴在context.py文件中,Process的定义也是在context.py文件中)。

67677新澳门手机版 10

 —— 管道(Pipe)
  这里精通管道是从类UNIX系统驾驭,因为其知晓起来更便于。管道在类UNIX系统中也是一种文件,在变化新的子进度的时候将八个经过都关乎至同多个管道上,那样正是双工通讯(父亲和儿子进程并行可读可写)。假诺要兑现单工通讯,就停业相应的大道(一方写一方读)【4】。

  首先是pickle模块。pickle模块是二个Python中故意的多寡格式,与JSON等不一样,是不能够被别的语言识别的格式。在Python中的官方文书档案【3】中比较了pickle模块与JSON的差别之处,以及介绍了pickle的利用原则。简单摘录如下:

 

引言
  最近希图上学一下怎么行使Python中的多进度。在翻看有关书籍、英特网资料时开掘具有代码都包含if __name__=="__main__",在试验的长河中窥见只要在运营代码进程中,未有那句话Python解释器就能报错。尽管Python对于multiprocessing的文书档案第17.2.1.1节中【1】关系必需这样使用,不过作者感觉并未根本上讲明清楚。由此作者决定从源码来解释自身的狐疑。

图1 对此类UNIX系统平台

  那几个字符串列表之后经过命令行送入系统,获得相应的子进程和子线程的句柄及子进度和子线程的ID号。在第65、66行是经过pickle方法将要求的多少从父进度传输给子进度。新进程是调用spawn.py文件中的spawn_main函数,如图6 spawnmain的定义。其中第100行的steal_handle()的效应是子进度获得父进度生成的句柄,用于后续通讯——使用pickle方法从父进度中读取供给数据。而主题素材的产出正是在那之后出现!该代码在第106行调用_main(),其次在第115行调用prepare(),再次运维到223行时,运营_fixup_main_from_name(),而此时该函数会运营父进程的本子。因而对此从未if__name__=="__main__"爱抚的代码都是要运维的,而此刻在其次次运营Process创造新历程的时候在第123行 if getattr(process.current_process(), '_inheriting', False): 时,由于子进度是兼具_inheriting属性,由此会激起出上述错误代码。

本文由67677新澳门手机版发布于计算机编程,转载请注明出处:67677新澳门手机版语句在调用多进程Process过程中

关键词: