进程和线程——Python中的实现

一、进程(Process

    进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。

    进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。

在Python中调用第三方模块multiprocessing,其过程就三步:

# 第一步:初始化multiprocess
# 第二步:start
# 第三步:join

import time
import multiprocessing
def process_run(params):
    time.sleep(2)
    print(params)
    time.sleep(2)
    print(params)
    time.sleep(2)
    print(params)


if __name__ == '__main__':
    params = 'old food sleepy is going to sleep'
    
    p = multiprocessing.Process(target=process_run, args=(params,))   # 实例化对象
    p.start()   # 开启进程
    print('lyb is lyb')
    p.join()   # 关闭
    print('lyb is lyb')

进程池:

    使用multiprocessing模块提供的Pool方法.

    初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行,请看下面的实例:

import multiprocessing
import time

def process_run(params):
    time.sleep(2)
    print('tomato' + params)
    time.sleep(2)
if __name__ == '__main__':
    # 第一步
    pool = multiprocessing.Pool(2)
    for i in range(0, 10):
        pool.apply_async(process_run, ('My English is very good' + str(i),))
    # 第二步
    pool.close()
    # 第三步
    pool.join()

二、线程(Thread)

    通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。

    线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉所以多进程的程序要比多线程的程序健壮。

在Python中开启线程用模块threading里面的Thread类,也是三步走:

# 第一步:创建 threading的类
# 第一步:执行start
# 第一步:等待结束 join
import threading
import time

def th_run(params):
    time.sleep(2)
    print(params)
    time.sleep(2)

if __name__ =='__main__':
    params = 'black potato is a good boy'
    # 创建Thread类, 传入两个参数
    t = threading.Thread(target=th_run, args=(params,))
    # 执行
    t.start()
    print('sunyang is good at swimming')
    time.sleep(2)
    print('sunyang is good at swimming')
    time.sleep(2)
    #等待结束
    t.join()

线程池:

Python中线程池的创建用第三方库threadpool里面的ThreadPool类:(感觉不怎么常用)

import threadpool
import time

def thread_run(params, cuolechileni):
    time.sleep(2)
    print('tomato' + params + cuolechileni)
    time.sleep(2)

# 有多少条thread
pool = threadpool.ThreadPool(2)

params = [(['我用java','aaa'], None),(['我用php', 'bbb'],None), (['我学区块链','ccc'], None), (['我学大数据', 'ddd'], None)]

# 创建函数和参数的类
requests = threadpool.makeRequests(thread_run, params)

for req in requests:
    pool.putRequest(req)
    print('lala 我们在这了,' + str(req))

pool.wait()
print('我才是最后的boss')

下面给出一个进程、进程池的应用实例:(爬取喜马拉雅音频文件),具体分析略

import requests
from lxml import etree
from urllib import request
import time, os
from multiprocessing import Queue, Pool, Process


def paqu(q):
    page = 1
    while page <= 4:
        url1 = 'https://www.ximalaya.com/xiangsheng/9742789/p{}/'.format(page)
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
        
        response = requests.get(url1, headers=headers)
        res_html = response.text
        
        res_lxml = etree.HTML(res_html)
        res_href = res_lxml.xpath('//ul[@class="dOi2"]/li/div[2]/a/@href')  # ['/xiangsheng/9742789/46430555', '/x0
        # print(res_href)
        for href1 in res_href:
            href_one = request.urljoin(url1, href1)  # https://www.ximalaya.com/xiangsheng/9742789/46105777
            # print(href_one)
            
            href_last = href_one.split('/')[-1]  # 46430555
            # print(href_last)
            url2 = 'https://www.ximalaya.com/revision/play/tracks?trackIds={}'.format(href_last)
            response_one = requests.get(url2, headers=headers)
            json_dict = response_one.json()
            # print(json_dict)
            
            src_str = json_dict['data']['tracksForAudioPlay'][0]['src']
            # print(src_str)
            if os.path.exists('Download_mp3'):
                pass
            else:
                os.mkdir('Download_mp3')
                
            trackName = 'Download_mp3/' + json_dict['data']['tracksForAudioPlay'][0]['trackName']
            # print(trackName)
            
            q.put((src_str, trackName))   # ----------------
            
            # request.urlretrieve(src_str, trackName + '.m4a')
            print(page)
        print('我是消息队列:', q.qsize())
        page += 1


def write_mp3(mp3_url_referer_url):
    time.sleep(5)
    (src_str, trackName) = mp3_url_referer_url
    print('开始下载', src_str, trackName)

    # request.urlretrieve(src_str, trackName + '.m4a')
    
    
if __name__ == '__main__':
    q = Queue()
    p = Process(target=paqu, args=(q,))
    p.start()
    

    # 开启的进程数量
    download_pool = Pool(5)
    while True:
        try:
            mp3_url_referer_url = q.get()   # 可以设置超时时间
            print(mp3_url_referer_url)
            download_pool.apply_async(write_mp3, (mp3_url_referer_url,))
        except:
            
            print('Queue is Empty!')
            break
    download_pool.close()
    download_pool.join()
    # 程序最后退出前进行join
    p.join()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值