热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【python】进程与线程

No1:多进程运行结果创建一个Process实例,用start()方法启动,join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。No2:进程池运行结果No3:

No1:

多进程

from multiprocessing import Process
import os

# 子进程要执行的代码
def run_proc(name):
    print(Run child process %s (%s)... % (name, os.getpid()))

if __name__==__main__:
    print(Parent process %s. % os.getpid())
    p = Process(target=run_proc, args=(test,))
    print(Child process will start.)
    p.start()
    p.join()
    print(Child process end.)

运行结果

技术分享图片

创建一个Process实例,用start()方法启动,join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。

No2:

进程池

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)
    end = time.time()
    print(Task %s runs %0.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 for all subprocesses done...)
    p.close()
    p.join()
    print(All subprocesses done.)

运行结果

技术分享图片

No3:

子进程

import subprocess

print($ nslookup www.python.org)
r = subprocess.call([nslookup,www.python.org])
print(Exit code:,r)

运行结果

技术分享图片

No4:

import subprocess

print($ nslookup)
p=subprocess.Popen([nslookup],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
output,err=p.communicate(bset q=mx\npython.org\nexit\n)
print(output.decode(utf-8))
print(Exit code:,p.returncode)

运行结果

技术分享图片

No5:

进程间通信

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()

在Unix/Linux下,可以使用fork()调用实现多进程。

要实现跨平台的多进程,可以使用multiprocessing模块。

进程间通信是通过QueuePipes等实现的。

No6:

多线程

Python的标准库提供了两个模块:_threadthreading_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

import time,threading

def loop():
    print(thread %s is running... % threading.current_thread().name)
    n=0
    while n<5:
        n=n+1
        print(thread %s >>> %s % (threading.current_thread().name,n))
        time.sleep(1)
    print(thread %s ended. % threading.current_thread().name)
    
print(thread %s is running... % threading.current_thread().name)
t = threading.Thread(target=loop,name=LoopThread)
t.start()
t.join()
print(thread %s ended. % threading.current_thread().name)

运行结果

技术分享图片

No7:

锁Lock

import time,threading

blance=0
lock=threading.Lock()

def run_thread(n):
    for i in range(100000):
        lock.acquire()
        try:
            change_it(n)
        finally:
            lock.release()

死锁

import threading,multiprocessing

def loop():
    x=0
    while True:
        x = x^1

for i in range(multiprocessing.cpu_count()):
    t = threading.Thread(target=loop)
    t.start()

Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

GIL是Python解释器设计的历史遗留问题,通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个不带GIL的解释器。

所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。

不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

No8:

ThreadLocal

import threading

local_school=threading.local

def process_student():
    std = local_school.student
    print(Hello,%s (in %s) % (std,threading.current_thread().name))
    
def process_thread(name):
    local_school.student=name
    process_student()

t1=threading.Thread(target=process_thread,args=(Alice,),name=Thread-A)
t2=threading.Thread(target=process_thread,args=(Bob,),name=Thread-B)
t1.start()
t2.start()
t1.join()
t2.join()

No9:

分布式进程

# task_master.py

import random, time, queue
from multiprocessing.managers import BaseManager

# 发送任务的队列:
task_queue = queue.Queue()
# 接收结果的队列:
result_queue = queue.Queue()

# 从BaseManager继承的QueueManager:
class QueueManager(BaseManager):
    pass

# 把两个Queue都注册到网络上, callable参数关联了Queue对象:
QueueManager.register(get_task_queue, callable=lambda: task_queue)
QueueManager.register(get_result_queue, callable=lambda: result_queue)
# 绑定端口5000, 设置验证码‘abc‘:
manager = QueueManager(address=(‘‘, 5000), authkey=babc)
# 启动Queue:
manager.start()
# 获得通过网络访问的Queue对象:
task = manager.get_task_queue()
result = manager.get_result_queue()
# 放几个任务进去:
for i in range(10):
    n = random.randint(0, 10000)
    print(Put task %d... % n)
    task.put(n)
# 从result队列读取结果:
print(Try get results...)
for i in range(10):
    r = result.get(timeout=10)
    print(Result: %s % r)
# 关闭:
manager.shutdown()
print(master exit.)
# task_worker.py

import time, sys, queue
from multiprocessing.managers import BaseManager

# 创建类似的QueueManager:
class QueueManager(BaseManager):
    pass

# 由于这个QueueManager只从网络上获取Queue,所以注册时只提供名字:
QueueManager.register(get_task_queue)
QueueManager.register(get_result_queue)

# 连接到服务器,也就是运行task_master.py的机器:
server_addr = 127.0.0.1
print(Connect to server %s... % server_addr)
# 端口和验证码注意保持与task_master.py设置的完全一致:
m = QueueManager(address=(server_addr, 5000), authkey=babc)
# 从网络连接:
m.connect()
# 获取Queue的对象:
task = m.get_task_queue()
result = m.get_result_queue()
# 从task队列取任务,并把结果写入result队列:
for i in range(10):
    try:
        n = task.get(timeout=1)
        print(run task %d * %d... % (n, n))
        r = %d * %d = %d % (n, n, n*n)
        time.sleep(1)
        result.put(r)
    except Queue.Empty:
        print(task queue is empty.)
# 处理结束:
print(worker exit.)

【python】进程与线程


推荐阅读
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 2023 ARM嵌入式系统全国技术巡讲旨在分享ARM公司在半导体知识产权(IP)领域的最新进展。作为全球领先的IP提供商,ARM在嵌入式处理器市场占据主导地位,其产品广泛应用于90%以上的嵌入式设备中。此次巡讲将邀请来自ARM、飞思卡尔以及华清远见教育集团的行业专家,共同探讨当前嵌入式系统的前沿技术和应用。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 本文介绍如何通过Windows批处理脚本定期检查并重启Java应用程序,确保其持续稳定运行。脚本每30分钟检查一次,并在需要时重启Java程序。同时,它会将任务结果发送到Redis。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 如何在WPS Office for Mac中调整Word文档的文字排列方向
    本文将详细介绍如何使用最新版WPS Office for Mac调整Word文档中的文字排列方向。通过这些步骤,用户可以轻松更改文本的水平或垂直排列方式,以满足不同的排版需求。 ... [详细]
  • 理解存储器的层次结构有助于程序员优化程序性能,通过合理安排数据在不同层级的存储位置,提升CPU的数据访问速度。本文详细探讨了静态随机访问存储器(SRAM)和动态随机访问存储器(DRAM)的工作原理及其应用场景,并介绍了存储器模块中的数据存取过程及局部性原理。 ... [详细]
  • 几何画板展示电场线与等势面的交互关系
    几何画板是一款功能强大的物理教学软件,具备丰富的绘图和度量工具。它不仅能够模拟物理实验过程,还能通过定量分析揭示物理现象背后的规律,尤其适用于难以在实际实验中展示的内容。本文将介绍如何使用几何画板演示电场线与等势面之间的关系。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
author-avatar
asdfu_814
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有