VII Python (8)并行开发

In [1]: import this

The Zen of Python, by Tim Peters

 

Beautiful is better than ugly.

Explicit is better than implicit.

Simple is better than complex.

Complex is better than complicated.

Flat is better than nested.

Sparse is better than dense.

Readability counts.

Special cases aren't special enough tobreak the rules.

Although practicality beats purity.

Errors should never pass silently.

Unless explicitly silenced.

In the face of ambiguity, refuse thetemptation to guess.

There should be one-- and preferably onlyone --obvious way to do it.

Although that way may not be obvious atfirst unless you're Dutch.

Now is better than never.

Although never is often better than *right*now.

If the implementation is hard to explain,it's a bad idea.

If the implementation is easy to explain,it may be a good idea.

Namespaces are one honking great idea --let's do more of those!

译:

Python的祖宗,作者Tim Peters

美丽优于丑陋

清楚优于含糊

简单优于复杂

复杂优于繁琐

平坦优于曲折

宽松优于密集

重要的是可读性

特殊的案例不足以特殊到破坏规则

尽管实践可以打败真理

错误却不可置之不理

除非另有明确要求

面对模棱两可,拒绝猜测

总会有一个——最好是只有一个——显而易见的方式来明辨

哪怕这种方式在开始的时候可能并不明显——除非你是荷兰人

现在有比没有好

尽管没有经常好于现在

如果如何实现很难被解释清楚,那么这个想法就是一个坏想法

如果如何实现可以被很好的解释,那么这是一个好想法

命名空间就是一个非常好的想法——让我们在这方面多做些工作吧

 

解决现实世界的问题,不在于开发语言本身,而在于对方法论的参透和对现实世界的理解,编程语言只是个工具

Python网络程序开发:

掌握程序开发世界的思想理论基础;

掌握Python程序开发的基础(容器、语法特性、map&reduce等等);

掌握Python解释型脚本语言的特性(动态类型);

掌握Python进行网络开发(C/S网络开发、爬虫使用、B/S网络开发);

并行开发(fork&thread&threading);socket编程;DjangoPython WEB框架),开发web应用;Twisted(是一个基于Python高效的网络开发框架),实现网络应用服务器;

numpy(数据分析用,数据展示的应用,对python下的数学分析提供强大的数学运算);

 

注:

Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是CMS(内容管理系统)软件。并于20057月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的;

NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix))。据说NumPyPython相当于变成一种免费的更强大的MatLab系统。NumPyNumeric Python)提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。多为很多大型金融公司使用,以及核心的科学计算组织如:Lawrence LivermoreNASA用其处理一些本来使用C++FortranMatlab等所做的任务;

 

 

编程世界的主流思想:

a、结构化编程、面向过程的开发(如下图,功能分解(功能不断细化,相当于C中的函数和python中的模块);数据流图(数据本身是静态的,不断的加工处理,相当于C中的结构体);这是早期崇尚个人英雄主义的时期最简单的方法论;缺陷:思想面窄,大型软件/系统开发会变得繁琐复杂、不易管理);

wKioL1eilZ_xkgB6AABRY796oUU440.jpg

b、函数式编程(数学中入演算,pythonlambda表达式,代表语言LISPErlang;尾递归、栈的使用;避免防御式编程;Erlang(最早源于交换机的应用延伸出的分布式开发语言,遵循OTP原则(热升级,给电信方面的应用升级时不能让通信中断,一旦新版本出问题会自动回滚到旧版本),非常出色的分布式开发语言,在分布式开发上与其它语言比非常便利;Erlang的一个重要思想,避免防御式编程,只要有错误就抛出,Erlang内部机制会根据不同的错误做出处理(在JAVA等面向对象编程语言中,初级程序员无论什么错误都用try...catch封装,这样在逻辑复杂的程序中产生的bug是很难追踪的));尾递归、栈的使用(在其它语言中递归通常被认为性能低下、不友好的编写方式,例如在python中使用递归嵌套到1K层时程序就会崩溃;而尾递归,它优化了栈的使用,不论使用多少个迭代,只使用一个栈,这样程序在性能和空间方面有出色的表现,尾递归在正常书写情况下程序是不会崩溃和溢出的);

cER实体关系模型(django框架要用到,关系数据库的理论基础3NF;选择、投影、笛卡尔操作join;静态模型,被描述成二维表格,实体----关系----实体);

d、面向对象(如图,很庞大的理论体系,整合了之前软件开发的思想,主要从客观世界出发,抽象出对象,对象间关系(包含关系、继承关系、关联关系)抽象为类,面向对象的包含关系两种(组合关系、聚合关系,区别:组成对象的所有子对象的生命周期与构成整体对象的生命周期是否一致);对象(属性和行为,属性(描述对象的静态特征),行为(对象的动态特征));面向对象分为三阶段(OOA-->OOD-->OOPanalysisdesignprogram),面向对象的主要目标:实现软件的高度复用);

wKioL1eilbCSVv6AAADEzTh8uPA856.jpg

 

解释型脚本语言的特点:

解释型(编译器和解释器集成,直接运行)和编译型(JAVAC.NET写好后要编译,编译完才能运行);

运行时(动态的状态,要与编译时作相对比较,编译时的代码是在硬盘上的,运行时是从硬盘加载到内存中运行的)和动态类型(只有运行时才知道变量是什么类型,大大增强了程序开发的灵活性);

强类型和弱类型(python是弱类型,在运行时才知道变量是什么类型);

开发效率高;

通用性强(跨平台);

内置方便的数据容器;

易于扩展和嵌入(与各语言互操作);

wKioL1eimFHias9aAABRMYUmPU8321.jpg

注:

在目前的网络软件体系结构中,并不是某一种语言一枝独秀,而是由多种语言混合编程;

C是永恒的经典,在有C的基础上再使用其它语言编程将时刻有内存的概念;

lualua的解释器仅100+K,嵌入式设备由于有内存的限制,在用lua编写一些脚本或程序将会很简洁,lua在游戏方面会作为配置脚本嵌入到混合编程中,在移动应用方面更多的是作为辅助语言,如配置等);

Shell用于运维,ASP已退出历史舞台,JAVA本身很庞大、笨重,网络应用逐渐的转到解释型语言上;

JAVA Applet会慢慢退出历史舞台,flex ASactionscript)多用于client的应用,如网络游戏;

HTML(静态的标签语言,描述性语言,仅用来浏览器解释并展示给用户的界面);Java Script(用于更多的应用,在浏览器端作ajax的脚本);

Android(可用java方式或NDKCC++系列)方式,对于android应用性能要求高的场景要用NDK方式编写;android中的java与传统网络应用中的java有很大的不同,如android16M内存限制要求代码效率要高,androidjavaGC机制是个灾难,在androidGC会有几百ms的时间损耗,若有过多创建新对象的操作,GC会让应用有明显的迟钝);

objective-c基于C系,语法表示模式较怪异,可自行控制内存(调试和释放内存),可编写写性能优异的移动应用,若在android中用java编写难度大,尤其是游戏方面的开发在加载素材较多时就得小心谨慎);

HTML5(现今在移动开发方面较热,号称跨androidios平台,不建议写跨平台的应用,因为平台间的特性有很大的不同,尽量用该平台最擅长的语言实现);

python(适用范围非常广,网络应用、网络交互、嵌入式应用都有它的身影,且资源非常丰富,有强大的各种类库,这大大节省开发软件的时间,提高了效率);

 

注:附加(2016所使用编程语言中工程师的薪资前三名:XcodeRubyGo):

Xcode 是运行在操作系统Mac OS X上的集成开发工具(IDE),由苹果公司开发。Xcode是开发OS X  iOS 应用程序的最快捷的方式。Xcode具有统一的用户界面设计,编码、测试、调试都在一个简单的窗口内完成。

Ruby,一种简单快捷的面向对象(面向对象程序设计)脚本语言,在20世纪90年代由日本人松本行弘(Yukihiro Matsumoto)开发,遵守GPL协议和Ruby License。它的灵感与特性来自于 PerlSmalltalkEiffelAda以及 Lisp 语言。由Ruby 语言本身还发展出了JRubyJava平台)、IronRuby.NET平台)等其他平台的 Ruby 语言替代品。Ruby的作者于1993224日开始编写Ruby,直至199512月才正式公开发布于fj(新闻组)。因为Perl发音与6月诞生石pearl(珍珠)相同,因此Ruby7月诞生石ruby(红宝石)命名。Ruby明显比其他类似的编程语言(如PerlPython)年轻,又因为Ruby是日本人发明的,所以早期的非日文资料和程序都比较贫乏,所以在网上仍然可以找到类似“Ruby的资料太少”之类的批评。约于2000年,Ruby开始进入美国,英文的资料开始发展。Ruby归根结底源于PerlPython两类语言,与CC++C#java是不同大类。

Go是一种新的语言,一种并发的、带垃圾回收的、快速编译的语言。它具有以下特点:它可以在一台计算机上用几秒钟的时间编译一个大型的Go程序。Go为软件构造提供了一种模型,它使依赖分析更加容易,且避免了大部分C风格include文件与库的开头。Go是静态类型的语言,它的类型系统没有层级。因此用户不需要在定义类型之间的关系上花费时间,这样感觉起来比典型的面向对象语言更轻量级。Go完全是垃圾回收型的语言,并为并发执行与通信提供了基本的支持。按照其设计,Go打算为多核机器上系统软件的构造提供一种方法。Go是一种编译型语言,它结合了解释型语言的游刃有余,动态类型语言的开发效率,以及静态类型的安全性。它也打算成为现代的,支持网络与多核计算的语言。要满足这些目标,需要解决一些语言上的问题:一个富有表达能力但轻量级的类型系统,并发与垃圾回收机制,严格的依赖规范等等。这些无法通过库或工具解决好,因此Go也就应运而生了。

 

wKiom1einBeRqf0-AAEtK1M79aE570.jpg

注:学习Python正当时,后端开发技术领域广泛,JavaPHPNode.js一直是领头的地位,不过可看出,随着大数据、人工智能和VR技术的大力发展,Python所涉及的框架被越来越多的应用起来,Django更是凭借易学易用的特点排名前6,所以若想尝试一个新的领域,Python不失为学习的首选。


方法论:

笛卡尔方法论(拆分、排序、处理、归并,复杂问题拆分成简单问题,对拆分后的问题由易到难进行排序,对各问题进行处理,将处理的各子问题归并);

软件工程过程方法论(软件生命周期、RUP统一软件过程管理(核心,面向对象)、敏捷开发(是目标));

项目管理(计划、组织、执行、控制);

注:单任务-->多任务;文字界面-->图形界面;单线程-->多线程;平台相关-->跨平台;单机(本地)-->网络(分布式);单一语言-->多种语言

 

程序员的境界:

线性级(思维简单,垒代码,组织不条理,导致后续程序维护及修改很麻烦);

逻辑级(掌握了算法理论基础,对业务的逻辑有清晰的把握,能编写逻辑较严密的模块、函数及程序,bug较少);

架构级(除对程序本身的把握,还要对现实世界的业务逻辑有清晰的把握,对软件进行架构分层,指导团队成员按统一目标实现);

工程级(不仅软件开发方面,还有项目管理要素,如计划、组织、执行、控制,如果有了项目管理的指导原则,对于软件工程的过程管理就会有一种一览众山小的状态);

程序员的陋习(自我、封闭、惯性、沟通障碍、一叶障目、工作量估计乐观、拒绝变化、拒绝重构);

 

Python开发环境:

win上,安装好python-2.7.11.msisetuptools-06C11.win32-py27.exe后,若要在cmd下运行pythoneasy_install MODULE安装相关模块,要先设置环境变量(右键“我的电脑”-->“属性”-->“高级”-->“环境变量”-->“新建”-->依次填入变量名path、变量值“C:\Python27;C:\Python\Scripts-->确定;

注:win下的环境变量,多个变量值间用分号分隔;win上一般第三方库默认安装在安装目录下的Lib\site-packages\下,Linux上在安装目录下的lib/python2.7/site-packages/

wKiom1eimIDRgEQcAADV0_xCWOM537.jpg

 

Linux下安装了setuptools包后会有easy_install命令,此命令可在线安装所需模块,简单用法:#easy_install MODULE

[root@etiantian ~]# easy_install-2.7 --help

Global options:

  --verbose(-v)  run verbosely (default)

 --quiet (-q)    run quietly (turnsverbosity off)

 --dry-run (-n)  don't actually doanything

 --help (-h)     show detailed helpmessage

 --no-user-cfg   ignorepydistutils.cfg in your home directory

Options for 'easy_install' command:

 --prefix                  installation prefix

 --zip-ok (-z)              installpackage as a zipfile

 --multi-version (-m)       makeapps have to require() a version

 --upgrade (-U)             forceupgrade (searches PyPI for latest versions)

 --install-dir (-d)         installpackage to DIR

 --script-dir (-s)          installscripts to DIR

……

 

 

并行开发:

并行的世界(串行与并行;阻塞与非阻塞;共享与冲突;多线程与多进程的特点及区别);

多进程开发;多线程开发;

 

进程:

计算机程序只不过是磁盘中可执行的,二进制(或其它类型)的数据。它们只有在被读取到内存中,被操作系统调用的时候才开始它们的生命期。进程(有时被称为重量级进程)是程序的一次执行。每个进程都有自己的地址空间,内存,数据栈以及其它记录其运行轨迹的辅助数据。操作系统管理在其上运行的所有进程,并为这些进程公平地分配时间。

线程:

线程(有时被称为轻量级进程)跟进程有些相似,不同的是,所有的线程运行在同一个进程中,共享相同的运行环境。我们可以想像成是在主进程或“主线程”中并行运行的“迷你进程”。

 

多进程(LinuxUnix平台专属;fork()(派生子进程的方法);wait(父进程控制子进程的情况下使用);waitpidpipesignal;守护进程);

 

进程间通信,两个进程间交换数据或对数据进行处理,两种方式:pipe管道和signal信号

注:pipe一端输入一端输出,pipe有匿名管道和文件管道,例如MySQL配置文件中的socket =/tmp/mysql.sock就是用于进程间通信;

 

守护进程daemon(将子进程独立成后台进程的方式,即使父进程窗口关闭掉也不会影响子进程,在写服务器应用程序时要用到);

 

python下的多线程,两种方式:thread模块(函数方式);threading模块(面向对象的方式);共享变量与临界资源、锁机制(使得多线程下变量的使用不出问题);

Python通过两个标准库threadthreading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。threading基于Java的线程模型设计,锁(Lock)和条件变量(Condition)在Java中是对象的基本行为(每一个对象都自带了锁和条件变量),而在Python中则是独立的对象;应该避免使用thread模块,原因是它不支持守护线程。当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出,有时我们并不期望这种行为,这时就引入了守护线程的概念,threading模块则支持守护线程;

 

 

 

 

In [2]: import os

In [3]: help(os.fork)

fork(...)

   fork() -> pid

   Fork a child process.

   Return 0 to child process and PID of child to parent process.

In [4]: help(os.getpid)

getpid(...)

   getpid() -> pid

   Return the current process id

In [5]: help(os.getppid)

getppid(...)

   getppid() -> ppid

   Return the parent's process id.

 

In [6]: import time

In [7]: help(time.sleep)

sleep(...)

   sleep(seconds)

   Delay execution for a given number of seconds.  The argument may be

    afloating point number for subsecond precision.

 

In [8]:help(os.waitpid)

waitpid(...)   #status0表示等待子进程执行完毕,1表示不等待子进程执行完毕)

   waitpid(pid, options) -> (pid, status)

   Wait for completion of a given child process.

In [9]:help(os.pipe)

pipe(...)

   pipe() -> (read_end, write_end)

   Create a pipe.

In [10]: help(os.close)   #os.close(w)os.fdopen(r)见以下举例version10

close(...)

   close(fd)

   Close a file descriptor (for low level IO).

In [11]: help(os.fdopen)

fdopen(...)

   fdopen(fd [, mode='r' [, bufsize]]) -> file_object

   Return an open file object connected to a file descriptor.

 

In [12]: import signal

In [13]: help(signal)

NAME

   signal - This module provides mechanisms to use signal handlers inPython.

In [14]: print dir(signal)  

['ITIMER_PROF', 'ITIMER_REAL','ITIMER_VIRTUAL', 'ItimerError', 'NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS','SIGCHLD', 'SIGCLD', 'SIGCONT', 'SIGFPE', 'SIGHUP','SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT', 'SIGKILL', 'SIGPIPE', 'SIGPOLL', 'SIGPROF', 'SIGPWR','SIGQUIT', 'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM', 'SIGTRAP', 'SIGTSTP', 'SIGTTIN','SIGTTOU', 'SIGURG', 'SIGUSR1', 'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU','SIGXFSZ', 'SIG_DFL', 'SIG_IGN', '__doc__', '__name__', '__package__', 'alarm','default_int_handler', 'getitimer', 'getsignal', 'pause', 'set_wakeup_fd','setitimer', 'siginterrupt', 'signal']

[root@localhost ~]# kill -l   #(常用的有:15,默认SIGTERM传道的终止一个进程,让其与其它进程一一通信最后终止关闭;9SIGKILL暴力杀死一个进程,不告知直接杀死;2SIGINT中断一个前台进程,快捷键ctrl+c1SIGHUP让一个进程不用重启就可重读其配置文件,并让新的配置生效)

 1) SIGHUP       2) SIGINT        3) SIGQUIT      4) SIGILL          5) SIGTRAP

 6)SIGABRT     7) SIGBUS        8) SIGFPE         9) SIGKILL       10) SIGUSR1

11) SIGSEGV     12)SIGUSR2     13) SIGPIPE      14) SIGALRM   15) SIGTERM

16) SIGSTKFLT  17) SIGCHLD    18) SIGCONT    19) SIGSTOP     20)SIGTSTP

In [15]: help(signal.signal)

signal(...)

   signal(sig, action) -> action

   Set the action for the given signal. The action can be SIG_DFL,

   SIG_IGN, or a callable Python object. The previous action is

   returned.  See getsignal() forpossible return values.

 

In [17]: help(os.setsid)

setsid(...)

   setsid()

   Call the system call setsid().

In [18]: help(os.umask)

umask(...)

    umask(new_mask) -> old_mask

   Set the current numeric umask and return the previous umask.

In [20]: help(sys.exit)

exit(...)

   exit([status])

   Exit the interpreter by raising SystemExit(status).

   If the status is omitted or None, it defaults to zero (i.e., success).

   If the status is an integer, it will be used as the system exit status.

   If it is another kind of object, it will be printed and the system

   exit status will be one (i.e., failure).

 

In [21]: import thread

In [22]: help(thread.start_new_thread)   #(其中,function是将要调用的线程函数,args是传给线程函数的参数,必须是tuple类型,kwargs是可选参数;线程的结束一般依靠线程的自然结束,也可在线程函数中调用thread.exit()将抛出SystemExit exception达到退出线程的目的)

start_new_thread(...)

   start_new_thread(function, args[, kwargs])

   (start_new() is an obsolete synonym)

   Start a new thread and return its identifier.  The thread will call the

   function with positional arguments from the tuple args and keywordarguments

   taken from the optional dictionary kwargs.  The thread exits when the

   function returns; the return value is ignored.  The thread will also exit

   when the function raises an unhandled exception; a stack trace will be

   printed unless the exception is SystemExit.

In [23]: print dir(thread)

['LockType', '__doc__', '__name__', '__package__','_count', '_local', 'allocate', 'allocate_lock','error', 'exit', 'exit_thread', 'get_ident', 'interrupt_main', 'stack_size','start_new', 'start_new_thread']

In [24]: help(thread.allocate_lock)  

allocate_lock(...)

   allocate_lock() -> lock object

   (allocate() is an obsolete synonym)

   Create a new lock object.  Seehelp(LockType) for information about locks.

In [35]: mylock=thread.allocate_lock()

In [36]: mylock.<TAB>

mylock.acquire      mylock.acquire_lock mylock.locked        mylock.locked_lock   mylock.release       mylock.release_lock

In [37]: help(mylock.acquire)

acquire(...)

   acquire([wait]) -> bool

   (acquire_lock() is an obsolete synonym)

   Lock the lock.  Without argument,this blocks if the lock is already

   locked (even by the same thread), waiting for another thread to release

   the lock, and return True once the lock is acquired.

   With an argument, this will only block if the argument is true,

   and the return value reflects whether the lock is acquired.

    The blocking operation is not interruptible.

In [38]: help(mylock.release)

release(...)

   release()

   (release_lock() is an obsolete synonym)

   Release the lock, allowing another thread that is blocked waiting for

   the lock to acquire the lock.  Thelock must be in the locked state,

   but it needn't be locked by the same thread that unlocks it.

 

In [25]: import threading

In [26]: help(threading)

NAME

   threading - Thread module emulating a subset of Java's threading model.

In [27]: print dir(threading)

['BoundedSemaphore', 'Condition', 'Event','Lock', 'RLock', 'Semaphore', 'Thread', 'ThreadError', 'Timer', '_BoundedSemaphore','_Condition', '_DummyThread', '_Event', '_MainThread', '_RLock', '_Semaphore','_Timer', '_VERBOSE', '_Verbose', '__all__', '__builtins__', '__doc__','__file__', '__name__', '__package__', '_active', '_active_limbo_lock','_after_fork', '_allocate_lock', '_counter', '_deque', '_enumerate','_format_exc', '_get_ident', '_limbo', '_newname', '_pickSomeNonDaemonThread','_profile_hook', '_shutdown', '_sleep', '_start_new_thread', '_sys', '_test','_time', '_trace_hook', 'activeCount', 'active_count', 'currentThread','current_thread', 'enumerate', 'local', 'setprofile', 'settrace', 'stack_size','warnings']

In [28]: help(threading.Thread)

class Thread(_Verbose)

 |  Aclass that represents a thread of control.

| This class can be safely subclassed in a limited fashion.

In [29]: help(threading.RLock)

RLock(*args, **kwargs)

   Factory function that returns a new reentrant lock.

    Areentrant lock must be released by the thread that acquired it. Once a

   thread has acquired a reentrant lock, the same thread may acquire itagain

   without blocking; the thread must release it once for each time it has

   acquired it.

 

 

举例(多进程----forkwaitpidpipesignal

(version1)

[root@localhost ~]# vim fork_test.py   #(使用fork来派生子进程;if语句块是子进程执行的语句,在子进程中执行的语句会复制父进程内存空间的东西;else语句块是在父进程中执行的语句)

-------------script start----------

#!/usr/bin/python2.7

#

import os

 

def myfork():

       pid=os.fork()

       if pid==0:

                print 'this is child %d' % pid

       else:

                print 'this is parent %d' % pid

if __name__=='__main__':

       myfork()

------------script end-------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56647

this is child 0

 

(version2)

[root@localhost ~]# vim fork_test.py

-------------script start----------------

#!/usr/bin/python2.7

#

import os

 

def myfork():

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d'% (pid,os.getpid(),os.getppid())

       else:

                print 'this is parent%d--%d--%d' % (pid,os.getpid(),os.getppid())

if __name__=='__main__':

       myfork()

-------------script end----------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56673--56672--56587

this is child 0--56673--56672

 

注:比较version3-6,每次运行输出内容的顺序都有可能不一样,在消耗CPU时间不一样时,输出内容的顺序将发生变化,这说明在父进程和子进程中谁先调用哪些结果或谁先输出哪些结果是不确定的,这也是异步处理的基础

(version3)   #(此例执行时子进程应该输出2有可能没输出,原因:父进程执行完后直接退出处于回收状态,子进程之后的语句不会执行,可让父进程等待子进程执行完成后再进行之后的处理,使用os.waitpid()

[root@localhost ~]# vim fork_test.py

--------------script start-----------

#!/usr/bin/python2.7

#

import os

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child%d--%d--%d' % (pid,os.getpid(),os.getppid())

                print a+1

       else:

                print 'this is parent%d--%d--%d' % (pid,os.getpid(),os.getppid())

                print a+3

if __name__=='__main__':

       myfork()

------------scirpt end--------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56676--56675--56587

4

this is child 0--56676--56675

2

 

(version4)

[root@localhost ~]# vim fork_test.py

----------------script start-------------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(1)

                print a+1

       else:

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                print a+3

if __name__=='__main__':

       myfork()

--------------script end--------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56695--56694--56587

4

[root@localhost ~]# this is child 0--56695--1

2

 

(version5)

[root@localhost ~]# vim fork_test.py

-------------------script start-----------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                #time.sleep(1)

                print a+1

       else:

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(2)

                print a+3

if __name__=='__main__':

       myfork()

----------------script end--------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56702--56701--56587

this is child 0--56702--56701

2

4

 

(version6)

[root@localhost ~]# vim fork_test.py

--------------script start-------------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(1)

                print a+1

       else:

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(2)

                print a+3

if __name__=='__main__':

       myfork()

-----------------script end------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56707--56706--56587

this is child 0--56707--56706

2

4

 

(version7)   #(父进程一直等待子进程执行完成后才输出自己的值,此例将一直等待死循环)

[root@localhost ~]# vim fork_test.py

------------------script start-------------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(1)

                print a+1

                while True:

                        pass

       else:

                status=os.waitpid(pid,0)

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(2)

                print a+3

if __name__=='__main__':

       myfork()

------------script end----------------

[root@localhost ~]# python2.7 fork_test.py

this is child 0--56729--56728

2

 

(version8)   #(父进程在将自己的语句执行完成后一直等待子进程执行完毕才退出,B/S架构的web server应用就是监听在某个套接字上一直等待client的连接)

[root@localhost ~]# vim fork_test.py

------------script start--------------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(1)

                print a+1

                while True:

                        pass

       else:

                print 'this is parent %d--%d--%d' %(pid,os.getpid(),os.getppid())

                time.sleep(2)

                print a+3

                status=os.waitpid(pid,0)

if __name__=='__main__':

       myfork()

--------------script end----------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56763--56762--56587

this is child 0--56763--56762

2

4

 

(version9)   (将if语句块中的while语句块注释掉,查看type(status)的类型为元组,print status查看返回子进程的pid及子进程的状态)

[root@localhost ~]# vim fork_test.py

------------script start-------------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(1)

                print a+1

                #while True:

                        #pass

       else:

                                     status=os.waitpid(pid,0)

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(2)

                print a+3

                print type(status)

                print status

if __name__=='__main__':

       myfork()

---------------script end----------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56776--56775--56587

this is child 0--56776--56775

2

4

<type 'tuple'>

(56776, 0)

 

(version10)   #status=os.waitpid(pid,1)1表示不等待子进程执行完毕,会将子进程回收掉,再执行父进程之后的语句,而上例中0表示等待子进程执行完毕;在进程间处理同步的数据时就可通过os.waitpid(……)操作,0等待子进程,1不等待子进程立刻回收子进程)

[root@localhost ~]# vim fork_test.py

------------script start-------------

#!/usr/bin/python2.7

#

import os

import time

 

def myfork():

       a=1

       pid=os.fork()

       if pid==0:

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(3)

                print a+1

                #while True:

                        #pass

       else:

                status=os.waitpid(pid,1)

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                time.sleep(2)

                print a+3

                print type(status)

                print status

if __name__=='__main__':

       myfork()

--------------script end--------------

[root@localhost ~]# python2.7 fork_test.py

this is parent 56790--56789--56587

this is child 0--56790--56789

4

<type 'tuple'>

(0, 0)

[root@localhost ~]# 2

 

(version11)   #(进程间通信--pipe

[root@localhost ~]# vim fork_test.py

-----------------scirpt start-------------

#!/usr/bin/python2.7

#

import os

import time

def myfork():

       r,w=os.pipe()

       a=1

       pid=os.fork()

       if pid==0:

                os.close(r)

                w=os.fdopen(w,'w')

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                #time.sleep(1)

                #print a+1

                while a<100:

                        a+=1

                        w.write(str(a))

                w.close()

       else:

                os.close(w)

                r=os.fdopen(r)

                print r.read()

                r.close()

                print 'this is parent %d--%d--%d' % (pid,os.getpid(),os.getppid())

                #time.sleep(2)

                #print a+3

                status=os.waitpid(pid,0)

                print type(status)

                print status

if __name__=='__main__':

       myfork()

-------------------scriptend--------------------

[root@localhost ~]# python2.7 fork_test.py

this is child 0--56918--56917

23456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100

this is parent 56918--56917--56587

<type 'tuple'>

(56918, 0)

 

(version12)   #(进程间通信----signal,通过信号方式相互控制)

[root@localhost ~]# vim fork_test.py

--------------script start-----------

#!/usr/bin/python2.7

#

import os

import time

import signal

 

def onsignal_term(a,b):

       print 'over'

signal.signal(signal.SIGTERM,onsignal_term)

 

def myfork():

       r,w=os.pipe()

       a=1

       pid=os.fork()

       if pid==0:

                os.close(r)

                w=os.fdopen(w,'w')

                print 'this is child %d--%d--%d' % (pid,os.getpid(),os.getppid())

                #time.sleep(1)

                #print a+1

                while a<100:

                        a+=1

                        if a>60:

                                os.kill(os.getppid,signal.SIGTERM)

                        w.write(str(a))

                        print a

                w.close()

       else:

                os.close(w)

                r=os.fdopen(r)

                print r.read()

                r.close()

                print 'this is parent %d--%d--%d' %(pid,os.getpid(),os.getppid())

                #time.sleep(2)

                #print a+3

                status=os.waitpid(pid,0)

                print type(status)

                print status

if __name__=='__main__':

       myfork()

------------------------script end-------------

[root@localhost ~]# python2.7 fork_test.py

this is child 0--57012--57011

2

3

4

……

58

59

60

Traceback (most recent call last):

 File "fork_test.py", line 40, in <module>

   myfork()

 File "fork_test.py", line 24, in myfork

   os.kill(os.getpid,signal.SIGTERM)

TypeError: an integer is required

23456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960

this is parent 57012--57011--56587

<type 'tuple'>

(57012, 256)

 

 

 

举例(守护进程)

[root@localhost ~]# vim daemon_test.py

-----------------scritp start------------------

#!/usr/bin/python2.7

#

import os

import sys

 

def daemon_test():

       pid=os.fork()

       if pid>0:

                sys.exit(0)

       os.setsid()

       os.umask(0)

 

       pid=os.fork()

       if pid>0:

                sys.exit(0)

 

       f=open('/tmp/test.txt','w')

       a=1

       while True:

                a+=1

                f.write(str(a))

       f.close()

 

if __name__=='__main__':

       daemon_test()

--------------script end---------------

[root@localhost ~]# python2.7 daemon_test.py

[root@localhost ~]# ll -h /tmp/test.txt   #(开始执行后查看此文件会非常大,文件大小增长很快,要尽快终止掉此进程,否则将写满硬盘)

[root@localhost ~]# tail -f /tmp/test.txt

[root@localhost ~]# ps aux | grep python

[root@localhost ~]# kill -9 57132

 

 

举例(多线程----threadthreading):

(version1)   #(若不加time.sleep(10),运行时将不会有任何输出,因为脚本很快就执行到了最后,脚本的主进程被结束,马上被回收了,其下的线程将不存在了)

[root@localhost ~]# vim thread_test.py

----------------script start------------

#!/usr/bin/python2.7

#

import thread

import time

 

def funt(no,a):

       while True:

                a+=1

                print 'thread no %d = %d' %(no,a)

 

def testt():

        thread.start_new_thread(funt,(1,2))

        thread.start_new_thread(funt,(2,2))

 

if __name__=='__main__':

       testt()

        time.sleep(10)

------------------script end-----------------

[root@localhost ~]# python2.7 thread_test.py

……

thread no 1 = 40806

thread no 1 = 40807

thread no 1 = 40808

thread no 1 = 40809

thread no 1 = 40810

thread no 1 = 40811

……

thread no 2 = 44685

thread no 2 = 44686

thread no 2 = 44687

thread no 2 = 44688

thread no 2 = 44689

……

 

(version2)   #(两线程均可对全局变量作更改)

[root@localhost ~]# vim thread_test.py

------------------script start-----------------

#!/usr/bin/python2.7

#

import thread

import time

 

c=1

def funt(no,a):

        global c

       while True:

                c+=1

                print 'thread no %d = %d' %(no,c)

 

def testt():

       thread.start_new_thread(funt,(1,2))

       thread.start_new_thread(funt,(2,2))

 

if __name__=='__main__':

       testt()

       time.sleep(10)

-----------------script end----------------

[root@localhost ~]# python2.7 thread_test.py

……

thread no 2 = 61817

thread no 2 = 61818

thread no 1 = 61819

thread no 1 = 61820

……

 

(version3) 

[root@localhost ~]# vim threading_test.py

-----------------script start----------------

#!/usr/bin/python2.7

#

import threading

import time

 

count=0

class aa(threading.Thread):

       def __init__(self,no,interval):

                '''Constructor'''

                threading.Thread.__init__(self)

                self.no=no

                self.interval=interval

                self.isstop=False

       def run(self):

                global count

                while not self.isstop:

                        count+=1

                        print 'thread %d = %d'% (self.no,count)

                       time.sleep(self.interval)

        def stop(self):

                self.isstop=True

def factory():

       t1=aa(1,1)

       t1.start()

       t2=aa(2,2)

       t2.start()

       time.sleep(10)

       t1.stop()

       t2.stop()

if __name__=='__main__':

       factory()

--------------------script end---------------

[root@localhost ~]# python2.7threading_test.py

thread 1 = 1

thread 2 = 2

thread 1 = 3

thread 1 = 4

thread 2 = 5

thread 1 = 6

thread 1 = 7

thread 2 = 8

thread 1 = 9

thread 2 = 10

thread 1 = 11

thread 1 = 12

thread 1 = 13

thread 2 = 14

thread 1 = 15

 

(version4)   #(两个线程在对全局变量count作操作时,若不加锁很容易出问题,多线程在对变量操作时要加锁,操作完后再释放锁;count+=1为临界变量,此变量在两线程中操作)

[root@localhost ~]# vim threading_test.py

--------------------script start--------------

#!/usr/bin/python2.7

#

import threading

import time

 

mylock=threading.RLock()

count=0

class aa(threading.Thread):

       def __init__(self,no,interval):

                '''Constructor'''

                threading.Thread.__init__(self)

                self.no=no

                self.interval=interval

                self.isstop=False

       def run(self):

                global count

                for i in range(1,11):

                        mylock.acquire()

                        count+=1

                        mylock.release()

                        print 'thread %d = %d'% (self.no,count)

                #while not self.isstop:

                        #count+=1

                        #print 'thread %d = %d'% (self.no,count)

                       #time.sleep(self.interval)

       def stop(self):

                self.isstop=True

def factory():

       t1=aa(1,1)

       t1.start()

       t2=aa(2,2)

       t2.start()

       time.sleep(10)

       t1.stop()

       t2.stop()

if __name__=='__main__':

       factory()

-----------------script end----------------

[root@localhost ~]# python2.7 threading_test.py

thread 1 = 1

thread 1 = 2

thread 1 = 3

thread 1 = 4

thread 1 = 5

thread 1 = 6

thread 1 = 7

thread 1 = 8

thread 1 = 9

thread 1 = 10

thread 2 = 11

thread 2 = 12

thread 2 = 13

thread 2 = 14

thread 2 = 15

thread 2 = 16

thread 2 = 17

thread 2 = 18

thread 2 = 19

thread 2 = 20




本文转自 chaijowin 51CTO博客,原文链接:http://blog.51cto.com/jowin/1834185,如需转载请自行联系原作者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值