学习廖老师的py官网的笔记

多任务的实现方式有三种方式:

1、多进程

2、多线程

3、多进程+多线程(这种比较复杂,实际很少采用)

【多进程】

1、在mac中创建子进程使用Python封装的fork()系统调用。

import os

pid = os.fork()

pid

2、在windows上的实现。

使用multiprocessing模块的Process类。

为了观察,还加了一小段代码~

# -*- coding: utf-8 -*-

from multiprocessing import Process
import os # 这里是子进程要执行的代码
def run_proc(name):
print('Run child process %s (pid=%s)...' % (name, os.getpid())) if __name__=='__main__':
print('Parent process %s.' % os.getpid())
greeting = input('hi~')
print(greeting)
p = Process(target=run_proc, args=('MyTest',))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')

然后就观察到:

结束:

$python test.py
Parent process 1388.
hi~ hi!
hi!
Child process will start.
Run child process MyTest (pid=12680)...
Child process end.

join用于进程间的同步,子进程结束后继续往下执行。

3、有时候需要创建大量的进程,(比如应对多用户访问)这个时候就需要使用“进程池”。

#-*- coding: utf-8 -*-

from multiprocessing import Pool
import os, time, random def long_time_task(name):
print('run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3) # teme.sleep(sec)\random.random生成一个0<=x<1的数
end = time.time()
print('Task %s run %.2f seconds.' % (name, (end - start))) if __name__=='__main__':
print('Parent process %s' % os.getpid())
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i,)) # 初始化子进程:这里的意思应该是将任务分配给进程并添加参数
print('Waiting all process Done!. ..')
p.close() # 关闭进程池:调用之后就不能再添加新进程了
p.join() # 父进程等待:等待所有子进程执行完毕
print('ALL Done.')
Parent process 8936
Waiting all process Done!. ..
run task 0 (5608)...
run task 1 (11904)...
run task 2 (8212)...
run task 3 (7492)...
Task 0 run 0.86 seconds.
run task 4 (5608)...
Task 4 run 0.85 seconds.
Task 1 run 1.81 seconds.
Task 2 run 2.53 seconds.
Task 3 run 2.88 seconds.
ALL Done.

在join之后宏观来说各个进程应该是并发的,但是task4却在task0执行完之后才开始run。

原因是pool中设置了最大运行并行的进程个数。

    p = Pool(4) # 这里设置的是可以同时并发的数量
for i in range(8): # 真正添加的进程数量

run一下:

Parent process 7592
Waiting all process Done!. ..
run task 0 (4596)...
run task 1 (12712)...
run task 2 (9460)...
run task 3 (7308)...
Task 0 run 1.20 seconds.
run task 4 (4596)... # 因为已经有 4 个进程在并行了,因此 task 4需要等待一个进程结束才开始运行,后面的task也是同理,结束一个,加入一个。
Task 3 run 1.23 seconds.
run task 5 (7308)...
Task 4 run 1.26 seconds.
run task 6 (4596)...
Task 1 run 2.46 seconds.
run task 7 (12712)...
Task 2 run 2.63 seconds.
Task 5 run 1.63 seconds.
Task 6 run 0.95 seconds.
Task 7 run 1.92 seconds.
ALL Done.
p = Pool() # 不添加参数就默认为电脑的核数

4、子进程。

”很多时候,子进程并不是自身,而是一个外部进程。“这里看不懂。

#-*- coding: utf-8 -*-
import subprocess print('$ nslookup www.python.org')
r = subprocess.call(['nslookup', 'www.python.org'])
print('Exit code:', r)
D:\labs>python test.py
$ nslookup www.python.org
DNS request timed out.
timeout was 2 seconds.
服务器: UnKnown
Address: 218.85.157.99 非权威应答:
DNS request timed out.
timeout was 2 seconds.
名称: python.map.fastly.net
Address: 151.101.72.223
Aliases: www.python.org Exit code: 0

稍微修改一下,改成编译当前文件夹下的一个.cpp文件:

#-*- coding: utf-8 -*-
import subprocess print('$ g++ prog1.cpp -std=c++11')
r = subprocess.call(['g++', 'prog1.cpp', 'prog1.cpp'])
print('Exit code:', r)

效果和直接在命令行下输入命令是一样的。(.bat)

如果子进程还需要输入,则可以通过communicate()方法输入。

#-*- coding: utf-8 -*-
import subprocess print('subprocess $ python')
p = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'a = 1997\nprint(a)\n')
print('output:' + output.decode('utf-8'))
print('Exit code:', p.returncode)
D:\labs>python test.py
subprocess $ python
output:1997 Exit code: 0

5、进程间的通信。

#-*- coding: utf-8 -*-
# 进程间的通信,queue实现示例。
from multiprocessing import Process, Queue
import os, time, random # 这段代码由写数据的进程执行
def write(q):
print('Process to write: %s' % os.getpid())
for value in ['A', 'B', 'C']:
print('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random()) # 这段代码由读数据的进程执行
def read(q):
print('Process to read: %s' % os.getpid())
while True:
value = q.get(True)
print('Get %s from queue.' % value) if __name__ == '__main__':
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,)) pw.start()
pr.start()
pw.join()
pr.terminate() # pr默认无限循环,这里一旦pw结束就关掉pr

可以把含有read方法的进程看作服务器,把含有write看作客户端程序。。。q当作存放socket的队列。。

$ python test.py
Process to write: 27524
Put A to queue...
Process to read: 25572
Get A from queue.
Put B to queue...
Get B from queue.
Put C to queue...
Get C from queue.

【多线程】

1、Python中的线程模块有_thread和threading。_thread是threading的底层,通常使用threading就可以了。

2、线程的接口和进程的接口差不多。

任何进程默认启动一个线程。这个默认的线程叫做:MainThread

#-*- coding: utf-8 -*-

import time, threading

print('current_thread is %s' % threading.current_thread().name)
$ python test.py
current_thread is MainThread

MainThread又可以创建新的线程,方式和创建进程类似:

#-*- coding: utf-8 -*-

import time, threading

def f():
print('current_thread is %s' % threading.current_thread().name) print('current_thread is %s' % threading.current_thread().name)
t = threading.Thread(target=f, name='>_<')
t.start();
t.join();
print('current_thread is %s' % threading.current_thread().name)
$ python test.py
current_thread is MainThread D:\labs>python test.py
current_thread is MainThread
current_thread is >_<
current_thread is MainThread

默认的线程名为Thread-1Thread-2

3、多线程和多进程的不同在于,多进程中的每一个进程对程序中的变量都有“副本”,各自互不影响。

而多线程中的各个线程却“共享”变量。

尝试一下,线程的情况:

#-*- coding: utf-8 -*-

import time, threading

def f():
global data # 需要先声明一下
data = data + 5
print(data) data = 30 t = threading.Thread(target=f, name='>_<')
t2 = threading.Thread(target=f, name='( >_ <)')
t.start();
t2.start();
t.join();
t2.join();

最后输出的是40.

4、Lock.

#-*- coding: utf-8 -*-

import threading, time

lock1 = threading.Lock() # 创建锁

def task1():
lock1.acquire() # 获取锁
try:
for i in range(10):
print('execute task1...')
finally:
lock1.release() # 释放锁 def task2():
lock1.acquire() # 获取锁
try:
for i in range(10):
print('execute task2...')
finally:
lock1.release() # 释放锁 t1 = threading.Thread(target=task1)
t2 = threading.Thread(target=task2)
t1.start()
t2.start()
t1.join()
t2.join()

5、GIL锁。

历史遗留问题,可以通过执行多个py程序来跑满多核cpu。(或者)

【ThreadLocal】

参考:http://python.jobbole.com/86150/

有时候使用局部变量不太方便,所以就引入了threadlocal变量。这个变量实质是一个全局的dict,但是却提供储存局部数据的功能。

怎么创建、访问threadlocal储存的局部数据呢?

#-*- coding: utf-8 -*-

import threading, time

global_data = threading.local() # 创建

# 每个线程都可以通过 global_data.num 获得自己独有的数据,并且每个线程读取到的 global_data 都不同
def show():
print(threading.current_thread().getName(), global_data.num) def thread_cal():
global_data.num = 0
for i in range(1000):
global_data.num += 1
show() threads = []
for i in range(10):
threads.append(threading.Thread(target=thread_cal))
threads[i].start()
for i in range(10):
threads[i].join()

【进程vs线程】

相对而言,多进程稳定,但是消耗资源大,多线程不稳定,但是消耗资源小。

【分布式进程】

参考代码来源

# -*- coding: utf-8 -*-

import queue

from multiprocessing.managers import BaseManager

task_queue = queue.Queue()
result_queue = queue.Queue() class QueueManager(BaseManager):
pass def return_task_queue():
return task_queue def return_result_queue():
return result_queue def test():
QueueManager.register('get_task_queue', callable=return_task_queue)
QueueManager.register('get_result_queue', callable=return_result_queue) manager = QueueManager(address=('127.0.0.1', 5000), authkey=b'abc') manager.start() task = manager.get_task_queue()
result = manager.get_result_queue() for i in range(10):
task.put(i) for i in range(10):
print(result.get()) manager.shutdown() if __name__ == '__main__':
test()

自己写的死活运行不出来。。。

【Python】进程和线程的更多相关文章

  1. python 进程和线程

    python中的进程.线程(threading.multiprocessing.Queue.subprocess) Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就 ...

  2. Python进程、线程、协程

    进程和线程的解释 进程(process)和线程(thread)是操作系统的基本概念,计算机的核心是CPU,它承担了所有的计算任务: 单个CPU一次只能运行一个任务,代表单个CPU总是运行一个进程,其他 ...

  3. python进程、线程、协程(转载)

    python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资 ...

  4. Python进程和线程

    引入进程和线程的概念及区别 1.线程的基本概念 概念 线程是进程中执行运算的最小单位,是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但 ...

  5. Python进程、线程、协程详解

    进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. ...

  6. python——进程、线程、协程

    Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/env pytho ...

  7. Python进程与线程

    进程与线程:*进程: 进程是系统中程序执行和资源分配的基本单元, 每个进程都有自己的数据段(存储数据).代码段(存储代码).堆栈段(对象和变量). # 全局变量等资源在多个进程中不能          ...

  8. python进程和线程(六)

    协程 协程,又称微线程,纤程.英文名Coroutine.顾名思义,协程是协作式的,也就是非抢占式的程序(线程是抢占式的).协程的关键字是yield,一看到这个就想到了生成器对不对?那就顺便回顾一下生成 ...

  9. python 进程、线程与协程的区别

    进程.线程与协程区别总结 - 1.进程是计算器最小资源分配单位 - 2.线程是CPU调度的最小单位 - 3.进程切换需要的资源很最大,效率很低 - 4.线程切换需要的资源一般,效率一般(当然了在不考虑 ...

  10. python进阶:Python进程、线程、队列、生产者/消费者模式、协程

    一.进程和线程的基本理解 1.进程 程序是由指令和数据组成的,编译为二进制格式后在硬盘存储,程序启动的过程是将二进制数据加载进内存,这个启动了的程序就称作进程(可简单理解为进行中的程序).例如打开一个 ...

随机推荐

  1. tplink 703刷固件

    1.软件下载: ImageBuilder链接 如果是全新刷机的话,使用:http://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/open ...

  2. <转载> C++笔试、面试笔记

    这些东西有点烦,有点无聊.如果要去C++面试就看看吧.几年前网上搜索的.刚才看到,就整理一下,里面有些被我改了,感觉之前说的不对或不完善. 1.求下面函数的返回值( 微软) int func(x)  ...

  3. svn管理的项目迁移到tfs

    1.将.vs  .svn文件夹删除 2.连接tfs,签入代码

  4. iOS-tableView本地动画刷新

    比如:就拿删除tableView中一个Cell为例子. // XXXTableViewCellDelegate - (void)tapDeleteHelloUser:(CJHelloTableView ...

  5. JZOJ.5246【NOIP2017模拟8.8】Trip

    Description        多年之后,worldwideD厌倦竞争,隐居山林.       他的家乡开始发展起了旅游业,在一条很长的主干道上,有N个旅游景点,按顺序编号为1到N.根据游客们网 ...

  6. Android Download机制详解(一)DocumentUI部分

    在Android中Google为我们集成了一套十分便利的Download机制,用来下载网络上的资源文件.以此省去了我们编写和维护大量与Download相关的代码. 组成 Android中Downloa ...

  7. Powershell Get File/Disk Size

    知识点: 1.获取路径中的文件夹:Get-ChildItem $startFolder  | Where-Object {$_.PSIsContainer -eq $True} | Sort-Obje ...

  8. VC的CListCtrl控件

    1. CListCtrl 样式及设置 2. 扩展样式设置 3. 数据插入 4. 一直选中Item 5. 选中和取消选中Item 6. 得到CListCtrl中所有行的checkbox的状态 7. 得到 ...

  9. CMDB初步了解

    本节内容 浅谈ITIL CMDB介绍 Django自定义用户认证 Restful 规范 资产管理功能开发 浅谈ITIL TIL即IT基础架构库(Information Technology Infra ...

  10. 如何编译部署 UIKit 离线文档?

    如何编译部署 UIKit 离线文档? Whis is UIKit? Note:部署在 Windows 系统会出现路径错误情况,这里采用在 Debian 系统上进行编译和部署. 1. 安装一些前置工具 ...