Python之异步处理

同步处理,也被称为是阻塞式处理,是指程序执行到某个位置,会一直等待该命令执行完毕,然后继续执行后续逻辑。
异步处理,是指一段程序由多个线程或进程同时执行,从而提高软件性能。

一、多线程

线程是计算机调度的基本单位,一个进程至少有一个线程。线程是轻量级的,线程的启动、调度对操作系统来说所耗资源较少,所以大多数软件都涉及了多个线程来并行执行程序,从而提高运行速度。线程的调度不是认为控制的,而是由操作系统决定的,创建多线程只是为一个软件争取更多被调度到的机会。

  1. 创建新线程
# -*- coding: UTF-8 -*-
import threading
import time

def get_data_from_db():
    print("当前线程名称:{0}".format(threading.current_thread().name))
    for i in range(5):
        time.sleep(1) # 表示“睡眠”一秒

    print("{0} 线程执行完毕!".format(threading.current_thread().name))


if __name__ == "__main__":# 用于对当前模块进行测试。如果是直接执行当前模块,则判断为True;如果该模块被导入其他模块中,则判断为False.
    print("{0} 线程开始运行".format(threading.current_thread().name))
    thread = threading.Thread(target=get_data_from_db, name="新线程")#threading.Thread()创建了一个线程实例
    thread.start()# 表示启动创建的新线程
    thread.join()# 是一个阻塞式方法,表示在当前位置等待新线程结束,之后在在主线程继续执行
    print("{0} 线程执行完毕!".format(threading.current_thread().name))
  1. 多个线程共享一个进程的内存空间,多个线程同时修改一个全局变量,始终都能正确输出,这称为线程安全。python使用“锁”机制来保证线程安全。如下所示:
# -*- coding: UTF-8 -*-

import time, threading

global_score = 100

lock = threading.Lock()


def update_score(score):
    for i in range(200000):
        lock.acquire() # 获取“锁”
        global global_score
        global_score = global_score + score
        global_score = global_score - score
        lock.release() # 释放“锁”

threads = []
for i in range(10):
    thread = threading.Thread(target=update_score, args=(i * 10,)) # 创建10个线程对象,每个线程负责执行各自的回调函数update_score
    threads.append(thread)

for i in threads:
    i.start() # 将线程全部启动,但10个线程不会同时执行,每个线程获取到锁,在对全局变量操作结束后释放锁,中间不会切换线程,这个过程是原子性的。

for i in threads:
    i.join()

print("global_score值:", global_score)

二、多进程

文件是静态的,进程是动态的。不同进程是独立运行的,拥有各自的内存空间、数据资源、文件资源等。一个进程可以创建另一个进程,称为当前进程的子进程。

  1. 创建子进程
    Linux中使用fork方法创建子进程。windows中使用multiprocessing.Process创建子进程,如下所示:
# -*- coding: UTF-8 -*-

import time
from multiprocessing import Process
import os

def new_process(para):
    time.sleep(10)
    print("子进程ID:{0}".format(os.getpid()))
    print("主进程传递来的参数:{0}".format(para))


if __name__ == "__main__":
    print("父进程ID是:{0}".format(os.getpid()))
    process = Process(target=new_process, args=("主进程参数",))
    process.start()# 启动进程
    process.join()# 等待子进程执行完毕,再执行主进程
    print("主进程执行完毕!")
  1. 进程池

当主进程需要同时管理多个进程的时候,可以使用进程池。如下所示:

# -*- coding: UTF-8 -*-

from multiprocessing import Pool
import time


def proc(num):
    print("当前进程编号:{0} 开始执行".format(num))
    time.sleep(5)
    print("当前进程编号:{0} 执行结束".format(num))


if __name__ == "__main__":
    pool = Pool(3) # 创建一个进程池对象,并且进程池中同时运行的进程个数为3个
    print("创建5个进程")
    for i in range(5):
        process_num = "{0}".format(i)
        pool.apply_async(proc, args=(process_num,)) # 用于创建进程
    pool.close()# 表示不能再有新的进程加入pool
    pool.join() 
    print("主进程执行完毕!")
  1. 进程间通信
    python使用多进程 multiprocessing 模块提供了进程间通信的工具:Queue。一个进程往Queue中放数据,另一个进程从Queue中取数据,由此实现通信,如下所示:
# -*- coding: UTF-8 -*-

from multiprocessing import Process, Queue
import os, time


def set_data(q, tmp_list):
    for item in tmp_list:
        print("当前{0}进程将值 {1} 插入队列".format(os.getpid(), item))
        q.put(item)
        time.sleep(2)


def get_data(q, count):
    for i in range(count):
        value = q.get(True)
        print("当前{0}进程获取到值为:{1}".format(os.getpid(), value))


if __name__ == "__main__":
    que = Queue()
    data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    length = len(data)
    process1 = Process(target=set_data, args=(que, data))
    process2 = Process(target=get_data, args=(que, length))
    process1.start()
    process2.start()
    process2.join()
    print("主进程执行完毕!")

其执行结果如图:
在这里插入图片描述
也可以参考之间的博文:Python使用socket实现两进程之间的传输数据

三、协程

Python提供了async关键字创建的异步函数,就是协程。异步函数的返回值并不是该函数的执行结果,而是一个协程对象,协程对象调用send方法才会触发异步函数的执行。如下所示:

# -*- coding: UTF-8 -*-
import time


async def get_data_from_db(counter):
    data = []
    print("参数counter:", counter)
    for i in range(counter):
        time.sleep(1)
        data.append(i)
    return data

coroutine_obj = get_data_from_db(5)
print("异步函数返回值:",coroutine_obj)
try:
    coroutine_obj.send(None)
except Exception as e:
    print(e)

参考:《python数据分析与大数据处理》

  • 0
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值