python进阶03
进程线程不管哪门语言都是一块可以被重视的方向,下面一起学习学习python中的进程,线程
1.进程线程区别
通俗解释:一个程序QQ的运行就是一个进程运行;QQ中打开多个页面互不影响可以同时操作的每个页面的运作就是线程
专业解释:进程-担当系统分配资源(CPU时间,内存)基本单元;线程-程序执行的最小单元
2.进程
1)fork()
2.1.1:介绍
linux可以多进程操作,所以它能实现登录多个QQ;os模块封装了fork()方法能创建一个进程
操作系统会创建一个新的进程,复制父进程所有信息到子进程中;
fork()函数一定会得到一个返回值,子进程中为0,父进程中就是子进程的id号;
父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID;
getpid():放回当前进程标识;getppid():返回父进程标识
2.1.2:用法
import os rpid = os.fork()
if rpid<:
print("fork调用失败。")
elif rpid == :
print("我是子进程(%s),我的父进程是(%s)"%(os.getpid(),os.getppid()))
x+=
else:
print("我是父进程(%s),我的子进程是(%s)"%(os.getpid(),rpid)) print("父子进程都可以执行这里的代码") 运行结果:
我是父进程(),我的子进程是()
父子进程都可以执行这里的代码
我是子进程(),我的父进程是()
父子进程都可以执行这里的代码
2)注意
多进程中所有数据(包括全局变量)都各有一份,互不影响
3)multiprocessing
2.3.1:介绍
跨平台的非linux支持的多进程模块,提供了一个Process类代表一个进程对象
2.3.2:Process-进程创建
Process([group [, target [, name [, args [, kwargs]]]]])
target:表示这个进程实例所调用对象;
args:表示调用对象的位置参数元组;
kwargs:表示调用对象的关键字参数字典;
name:为当前进程实例的别名;
group:大多数情况下用不到;
Process类常用方法:
is_alive():判断进程实例是否还在执行;
join([timeout]):是否等待进程实例执行结束,或等待多少秒;
start():启动进程实例(创建子进程);
run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法;
terminate():不管任务是否完成,立即终止;
Process类常用属性:
name:当前进程实例别名,默认为Process-N,N为从1开始递增的整数;
pid:当前进程实例的PID值;
2.3.3 例子
from multiprocessing import Process
import os
from time import sleep # 子进程要执行的代码
def run_proc(name, age, **kwargs):
for i in range():
print('子进程运行中,name= %s,age=%d ,pid=%d...' % (name, age,os.getpid()))
print(kwargs)
sleep(0.5) if __name__=='__main__':
print('父进程 %d.' % os.getpid())
p = Process(target=run_proc, args=('test',), kwargs={"m":})
print('子进程将要执行')
p.start()
sleep()
p.terminate()
p.join()
print('子进程已结束')
运行结果:
父进程 .
子进程将要执行
子进程运行中,name= test,age= ,pid=...
{'m': }
子进程运行中,name= test,age= ,pid=...
{'m': }
子进程已结束
2.3.4 Process子类-进程创建
创建新的进程还能够使用类的方式,可以自定义一个类,继承Process类
例子:
from multiprocessing import Process
import time
import os #继承Process类
class Process_Class(Process):
#因为Process类本身也有__init__方法,这个子类相当于重写了这个方法,
#但这样就会带来一个问题,我们并没有完全的初始化一个Process类,所以就不能使用从这个类继承的一些方法和属性,
#最好的方法就是将继承类本身传递给Process.__init__方法,完成这些初始化操作
def __init__(self,interval):
Process.__init__(self)
self.interval = interval #重写了Process类的run()方法
def run(self):
print("子进程(%s) 开始执行,父进程为(%s)"%(os.getpid(),os.getppid()))
t_start = time.time()
time.sleep(self.interval)
t_stop = time.time()
print("(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start)) if __name__=="__main__":
t_start = time.time()
print("当前程序进程(%s)"%os.getpid())
p1 = Process_Class()
#对一个不包含target属性的Process类执行start()方法,就会运行这个类中的run()方法,所以这里会执行p1.run()
p1.start()
p1.join()
t_stop = time.time()
print("(%s)执行结束,耗时%0.2f"%(os.getpid(),t_stop-t_start))
4)进程池
当子进程不多,直接用multprocessing中的Process动态生成多个进程,但如果是很多,手动创建工作量很大,此时就可以用multprocessing模块提供的pool方法了
运行机制:初始化进程池时可以指定最大进程数,当有新请求会先看进程池运行进程是否达到最大进程数,没有就创建一个进程放入进程池来维护同时运行子进程
multiprocessing.Pool常用函数解析:
apply_async(func[, args[, kwds]]) :使用非阻塞方式调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
apply(func[, args[, kwds]]):使用阻塞方式调用func
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出, 必须在close或terminate之后使用;
例子:
from multiprocessing import Pool
import os,time,random def worker(msg):
t_start = time.time()
print("%s开始执行,进程号为%d"%(msg,os.getpid()))
#random.random()随机生成0~1之间的浮点数
time.sleep(random.random()*)
t_stop = time.time()
print(msg,"执行完毕,耗时%0.2f"%(t_stop-t_start)) po=Pool() #定义一个进程池,最大进程数3
for i in range(,):
#Pool.apply_async(要调用的目标,(传递给目标的参数元祖,))
#每次循环将会用空闲出来的子进程去调用目标
po.apply_async(worker,(i,)) print("----start----")
po.close() #关闭进程池,关闭后po不再接收新的请求
po.join() #等待po中所有子进程执行完成,必须放在close语句之后
print("-----end-----") 运行结果:
----start----
0开始执行,进程号为21466
1开始执行,进程号为21468
2开始执行,进程号为21467
执行完毕,耗时1.
3开始执行,进程号为21466
执行完毕,耗时1.
4开始执行,进程号为21467
执行完毕,耗时0.
5开始执行,进程号为21466
执行完毕,耗时1.
6开始执行,进程号为21468
执行完毕,耗时0.
7开始执行,进程号为21467
执行完毕,耗时0.
8开始执行,进程号为21466
执行完毕,耗时0.
9开始执行,进程号为21468
执行完毕,耗时1.
执行完毕,耗时1.
执行完毕,耗时1.
-----end-----
5)进程间的通信-Queue
Process之间有时也需要通信,操作系统提供了很多机制来实现进程间通信
2.5.1 Queue方法介绍
初始化Queue()对象时(例如:q=Queue()),若括号中没有指定最大可接收的消息数量,或数量为负值,那么就代表可接受的消息数量没有上限(直到内存的尽头); Queue.qsize():返回当前队列包含的消息数量; Queue.empty():如果队列为空,返回True,反之False ; Queue.full():如果队列满了,返回True,反之False; Queue.get([block[, timeout]]):获取队列中的一条消息,然后将其从列队中移除,block默认值为True;
例子
from multiprocessing import Process, Queue
import os, time, random # 写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print 'Put %s to queue...' % value
q.put(value)
time.sleep(random.random()) # 读数据进程执行的代码:
def read(q):
while True:
if not q.empty():
value = q.get(True)
print 'Get %s from queue.' % value
time.sleep(random.random())
else:
break if __name__=='__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 等待pw结束:
pw.join()
# 启动子进程pr,读取:
pr.start()
pr.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
print ''
print '所有数据都写入并且读完'
2.5.2 进程池中的Queue
如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue()
例子
#coding=utf- #修改import中的Queue为Manager
from multiprocessing import Manager,Pool
import os,time,random def reader(q):
print("reader启动(%s),父进程为(%s)"%(os.getpid(),os.getppid()))
for i in range(q.qsize()):
print("reader从Queue获取到消息:%s"%q.get(True)) def writer(q):
print("writer启动(%s),父进程为(%s)"%(os.getpid(),os.getppid()))
for i in "dongGe":
q.put(i) if __name__=="__main__":
print("(%s) start"%os.getpid())
q=Manager().Queue() #使用Manager中的Queue来初始化
po=Pool()
#使用阻塞模式创建进程,这样就不需要在reader中使用死循环了,可以让writer完全执行完成后,再用reader去读取
po.apply(writer,(q,))
po.apply(reader,(q,))
po.close()
po.join()
print("(%s) End"%os.getpid())
2.线程
1)threading模块
通过这个模块将thread封装能更好操作
2.1.1 注意:
一个进程所有线程共享全局变量,但这可能会造成线程安全
2)锁
当多个线程同时修改同一个共享数据时,需要进行同步控制
创建方式
#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire([blocking])
#释放
mutex.release()
例子
from threading import Thread, Lock
import time g_num = def test1():
global g_num
for i in range():
#True表示堵塞 即如果这个锁在上锁之前已经被上锁了,那么这个线程会在这里一直等待到解锁为止
#False表示非堵塞,即不管本次调用能够成功上锁,都不会卡在这,而是继续执行下面的代码
mutexFlag = mutex.acquire(True)
if mutexFlag:
g_num +=
mutex.release() print("---test1---g_num=%d"%g_num) def test2():
global g_num
for i in range():
mutexFlag = mutex.acquire(True) #True表示堵塞
if mutexFlag:
g_num +=
mutex.release() print("---test2---g_num=%d"%g_num) #创建一个互斥锁
#这个所默认是未上锁的状态
mutex = Lock() p1 = Thread(target=test1)
p1.start() p2 = Thread(target=test2)
p2.start() print("---g_num=%d---"%g_num)
锁好是好,但也可能造成死锁情况
局部变量是各个线程自己的非共享
3)TheadLocal
ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题
实实在在的解决了开发过程中的问题
用法:local_school = threading.local()
import threading # 创建全局ThreadLocal对象:
local_school = threading.local() def process_student():
# 获取当前线程关联的student:
std = local_school.student
print('Hello, %s (in %s)' % (std, threading.current_thread().name)) def process_thread(name):
# 绑定ThreadLocal的student:
local_school.student = name
process_student() t1 = threading.Thread(target= process_thread, args=('dongGe',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('老王',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()
python进阶03的更多相关文章
- python进阶03 继承
python进阶03 继承 一.继承 课堂练习:假设你正在参与一个魔幻类角色游戏的开发,公司需要腻味这个游戏设计两个角色的类: a.剑士 属性:1.角色名:2.角色等级:3.生命值:4.攻击力 行为: ...
- Python进阶03 模块
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们之前看到了函数和对象.从本质上来说,它们都是为了更好的组织已经有的程序,以方便 ...
- Python进阶量化交易专栏场外篇7- 装饰器计算代码时间
欢迎大家订阅<教你用 Python 进阶量化交易>专栏!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外已陆续推出一些手记来辅助同学们学习本专栏内容,目前已推出如下扩展篇: 在第一篇 ...
- python进阶11 正则表达式
python进阶11 正则表达式 一.概念 #正则表达式主要解决什么问题? #1.判断一个字符串是否匹配给定的格式,判断用户提交的又想的格式是否正确 #2.从一个字符串中按指定格式提取信息,抓取页面中 ...
- Python进阶:函数式编程实例(附代码)
Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...
- Python进阶 - 对象,名字以及绑定
Python进阶 - 对象,名字以及绑定 1.一切皆对象 Python哲学: Python中一切皆对象 1.1 数据模型-对象,值以及类型 对象是Python对数据的抽象.Python程序中所有的数据 ...
- Python进阶-继承中的MRO与super
Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...
- Python进阶 - 命名空间与作用域
Python进阶 - 命名空间与作用域 写在前面 如非特别说明,下文均基于Python3 命名空间与作用于跟名字的绑定相关性很大,可以结合另一篇介绍Python名字.对象及其绑定的文章. 1. 命名空 ...
- python进阶学习笔记(一)
python进阶部分要学习的内容: 学习目标: 1.函数式编程 1.1,什么是函数式编程 函数式编程是一种抽象计算的编程模式 不同语言的抽象层次不同: 函数式编程的特点: python支持的函数式编程 ...
随机推荐
- 读取文件之<绝对路径>与<相对路径>
前言:字符流.字节流读取文件,下面的代码是在网上找到的一个各种文件读取方式,还算比较详细,分享给大家. public class ReadFromFile { /** * 以字节为单位读取文件,常用于 ...
- Splitting Pile
Splitting Pile Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement Snuke a ...
- 记录--Gson、json转实体类、类转json
需要导入Gson jar包 最近在做一个java web service项目,需要用到jason,本人对java不是特别精通,于是开始搜索一些java平台的json类库. 发现了google的gson ...
- maven仓库添加本地jar
一.将jar添加到本地仓库的做法: 以下面pom.xml依赖的jar包为例: 实际项目中pom.xml依赖写法: <dependency> <groupId>org.sprin ...
- Sql注入_mysql盲注__二次注入
sleep盲注攻击 Sleep延迟:延迟盲注 If(条件,true,false): 条件成立,返回第二个参数,反之第三个参数 举例1:length id=1 union select 1,2,slee ...
- JmsTemplate 发送方式
---恢复内容开始--- 背景: 原来我准备是setDefaultDestinationName 设置队列的名称 发现 系统运行后 创建 的并不是队列 ,而是Topic , 自己看下源码,发现在创 ...
- 自定义表单验证--jquery validator addMethod的使用
原文地址:jquery validator addMethod 方法的使用作者:蜡笔小玄 jQuery.validate是一款非常不错的表单验证工具,简单易上手,而且能达到很好的体验效果,虽然说在项目 ...
- python错误笔记
1.print "hello world!";SyntaxError:Missing parentheses in call to ‘paint’ . Did you mean p ...
- 前端基础-html(2)
一.字体标签 字体标签包含:h1~h6.<font>.<u>.<b>.<strong>.<em>.<sup>.<sub&g ...
- MySql存储过程、函数
存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MyS ...