python并发编程

这篇具有很好参考价值的文章主要介绍了python并发编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、程序提速的方法

python并发编程,编程基础,python

二、python对并发编程的支持

  • 多线程:threading,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成;
  • 多进程:multiprocess,利用多核CPU的能力,真正的并行执行任务;
  • 异步IO:asyncio,当线程比较多时,切换线程也会占用CPU资源,可在单线程中利用CPU和IO同时执行的原理,实现函数异步执行;
  • 使用Lock对资源加锁,防止冲突访问;
  • 使用Queue实现不同线程/进程之间的数据通信,实现生产者-消费者模式;
  • 使用线程池Pool/进程池Pool,简化线程/进程的任务提交,等待结果、获取结果;
  • 使用subprocess启动外部程序的进程,并进行输入输出交互;

python子进程的启动方法:fork与spawn,参考子进程启动方式

三、python并发编程的三种方式

3.1 3种方式的区别和选择

多线程Thread,多进程Process,多协程Coroutine。
python并发编程,编程基础,python
python并发编程,编程基础,python

3.2 GIL

python并发编程,编程基础,python

四、实战

4.1 多线程

python并发编程,编程基础,python

4.1.1 多线程网页爬虫示例代码

  • blog_spider.py
import requests
from bs4 import BeautifulSoup

urls = [
    f"https://www.cnblogs.com/sitehome/p/{page}"
    for page in range(1, 50 + 1)
]


def craw(url):
    #print("craw url: ", url)
    r = requests.get(url)
    return r.text


def parse(html):
    # class="post-item-title"
    soup = BeautifulSoup(html, "html.parser")
    links = soup.find_all("a", class_="post-item-title")
    return [(link["href"], link.get_text()) for link in links]


if __name__ == "__main__":
    for result in parse(craw(urls[2])):
        print(result)
  • producer_consumer_spider.py
import queue
import blog_spider
import time
import random
import threading

# 生产者
def do_craw(url_queue: queue.Queue, html_queue: queue.Queue):
    while True:
        url = url_queue.get()
        html = blog_spider.craw(url)
        html_queue.put(html)
        print(threading.current_thread().name, f"craw {url}",
              "url_queue.size=", url_queue.qsize())
        time.sleep(random.randint(1, 2))

# 消费者
def do_parse(html_queue: queue.Queue, fout):
    while True:
        html = html_queue.get()
        results = blog_spider.parse(html)
        for result in results:
            fout.write(str(result) + "\n")
        print(threading.current_thread().name, f"results.size", len(results),
              "html_queue.size=", html_queue.qsize())
        time.sleep(random.randint(1, 2))


if __name__ == "__main__":
    url_queue = queue.Queue()
    html_queue = queue.Queue()
    for url in blog_spider.urls:
        url_queue.put(url)
	#创建生产者线程
    for idx in range(3):
        t = threading.Thread(target=do_craw, args=(url_queue, html_queue),
                             name=f"craw{idx}")
        t.start()

    fout = open("02.data.txt", "w")
    # 创建消费者线程
    for idx in range(2):
        t = threading.Thread(target=do_parse, args=(html_queue, fout),
                             name=f"parse{idx}")
        t.start()

4.1.2 线程安全问题

线程安全指某个函数在多线程环境中被调用时,能够正确的处理多个线程之间的共享变量,使程序功能正确完成。由于线程的执行随时会发生切换,就造成了不可预料的结果,出现线程不安全。

使用Lock解决线程安全:

import threading
import time

lock = threading.Lock()

class Account:
    def __init__(self, balance):
        self.balance = balance


def draw(account, amount):
    with lock:
        if account.balance >= amount:
            time.sleep(0.1)
            print(threading.current_thread().name,
                  "取钱成功")
            account.balance -= amount
            print(threading.current_thread().name,
                  "余额", account.balance)
        else:
            print(threading.current_thread().name,
                  "取钱失败,余额不足")


if __name__ == "__main__":
    account = Account(1000)
    ta = threading.Thread(name="ta", target=draw, args=(account, 800))
    tb = threading.Thread(name="tb", target=draw, args=(account, 800))

    ta.start()
    tb.start()

4.2 多进程

python并发编程,编程基础,python

python 线程池实线原理

4.3 异步IO(协程)

python并发编程,编程基础,python
使用协程的时候,要确保使用的库要支持协程,比如requests库不支持协程,可使用aiohttp.文章来源地址https://www.toymoban.com/news/detail-669014.html

import asyncio
import aiohttp
import blog_spider

# 信号量控制协程的并发度
semaphore = asyncio.Semaphore(10)


async def async_craw(url):
    async with semaphore:
        print("craw url: ", url)
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                result = await resp.text()
                await asyncio.sleep(5)
                print(f"craw url: {url}, {len(result)}")

# 创建时间循环
loop = asyncio.get_event_loop()

tasks = [
    loop.create_task(async_craw(url))
    for url in blog_spider.urls]

import time

start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print("use time seconds: ", end - start)

到了这里,关于python并发编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JUC 高并发编程基础篇

    • 1、什么是 JUC • 2、Lock 接口 • 3、线程间通信 • 4、集合的线程安全 • 5、多线程锁 • 6、Callable 接口 • 7、JUC 三大辅助类: CountDownLatch CyclicBarrier Semaphore • 8、读写锁: ReentrantReadWriteLock • 9、阻塞队列 • 10、ThreadPool 线程池 • 11、Fork/Join 框架 • 12、CompletableFuture 1 什么

    2024年02月07日
    浏览(49)
  • Rust基础拾遗--并发和异步编程

       通过 Rust程序设计-第二版 笔记的形式对Rust相关 重点知识 进行汇总,读者通读此系列文章就可以轻松的把该语言基础捡起来。 为什么一些看似正确的多线程惯用法却根本不起作用? 与“内存模型”有关 你最终会找到一种自己用起来顺手且不会经常出错的并发惯用法。

    2024年02月19日
    浏览(35)
  • 复习并发编程的基础知识(一)

    目录 进程和线程 并发和并行  如何创建一个线程? 1,继承Thread类  2,实现Runnable接口          3. Callable接口 线程Thread类的一些重要方法  守护线程: 时间长了,并发编程的基础知识总忘,来记录一下: 进程和线程 进程:资源分配的最小单元,什么是资源?CPU,内存,网

    2024年02月08日
    浏览(57)
  • Java面试_并发编程_线程基础

    进程是正在运行程序的实例, 进程中包含了线程, 每个线程执行不同的任务 不同的进程使用不同的内存空间, 在当前进程下的所有线程可以共享内存空间 线程更轻量, 线程上下文切换成本一般上要比进程上下文切换低(上下文切换指的是从一个线程切换到另一个线程) 并发是单个

    2024年02月07日
    浏览(49)
  • java并发编程:多线程基础知识介绍

    最初的计算机只能接受一些特定的指令,用户每输入一个指令,计算机就做出一个操作。当用户在思考或者输入时,计算机就在等待。这样效率非常低下,在很多时候,计算机都处在等待状态。 后来有了 批处理操作系统 ,把一系列需要操作的指令写下来,形成一个清单,一次

    2024年02月07日
    浏览(49)
  • 【Rust 基础篇】Rust 多线程:并发编程的艺术

    多线程是现代计算机编程中的重要概念,它允许程序同时执行多个任务,充分利用多核处理器的性能优势。在 Rust 中,多线程编程也得到了很好的支持,通过标准库提供的 std::thread 模块可以方便地创建和管理线程。本篇博客将详细介绍 Rust 中多线程的使用方法,包含代码示例

    2024年02月16日
    浏览(43)
  • python:并发编程(十二)

    本文将和大家一起探讨python的多协程并发编程 (下篇) ,使用内置基本库asyncio来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。 本文为python并发编程的第十二篇,上一篇文章地址如下: python:并发

    2024年02月09日
    浏览(31)
  • python:并发编程(十三)

    本文将和大家一起探讨python提供高级接口(进程池、线程池)的并发编程,使用内置基本库concurrent.futures来实现并发,先通过官方来简单使用这个模块。先打好基础,能够有个基本的用法与认知,后续文章,我们再进行详细使用。为什么说是concurrent.futures,而不是concurrent呢?

    2024年02月09日
    浏览(32)
  • python:并发编程(二十三)

    本文将和大家一起探讨python并发编程的实际项目:win图形界面应用 (篇五,共八篇) ,系列文章将会从零开始构建项目,并逐渐完善项目,最终将项目打造成适用于高并发场景的应用。 本文为python并发编程的第二十三篇,上一篇文章地址如下: python:并发编程(二十二)

    2024年02月11日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包