Python-并发-多线程-多进程

多线程

多线程写入到一个文件内
实现方式: 采用 concurrent 和 threading.lock 锁的方式 
           采用threading 模块和 queue的方式
		   
 方案01
   Executor.submit(fn, *args, **kwargs)
    submit返回一个Future对象。
	    其中future.result()的 
	    result方法的作用是拿到调用返回的结果。如果没有执行完毕就会去等待。
	    这里我们使用with操作符,
	      使得当任务执行完成之后,自动执行shutdown函数,而无需编写相关释放代码
    Executor.map(fn, *args, **kwargs)
     map(func, *iterables, timeout=None)  iterables:可以是一个能迭代的对象. 
  回调函数		 

代码示例

from concurrent.futures import ThreadPoolExecutor, as_completed
from threading import Lock
import random
from time import time


def judge_interval(n):
    """ # 多输入参数时,可以将输入组装成list,嵌套的list的方式提取输入参数 """
    if n > 25:
        raise Exception('Big> 25, now %s \n' % n)
    elif 10 <= n <= 25:
        return n*1000
    else:
        return -n


def multi_thread(input_nums, input_file):
    """ 多线程写入到一个文件内"""
    lock = Lock()
    with open(input_file, 'a') as input_file_obj:
        with ThreadPoolExecutor(max_workers=3) as executor:
            future_jobs = {executor.submit(judge_interval, num): num for num in input_nums}
            for job in as_completed(future_jobs):
                try:
                    # result() 方法可以获取任务的返回值
                    data = job.result()
                    # 获取程序的输入
                    data_input = future_jobs[job]
                    print(data_input, data)
                    with lock:
                        input_file_obj.write('input: %s  output: %s.\n' % (data_input, data))
                except Exception as e:
                    input_file_obj.write(str(e))


if __name__ == '__main__':
    start_time = time()
    log_file = r'C:\Users\ow\out.txt'
    nums = [random.randint(0, 40) for _ in range(0, 5)]
    multi_thread(nums, log_file)
    end_time = time()
    duration_time = (end_time-start_time)
    print(f"用时 {duration_time}秒")

多线程操作

多线程计算-代码示例
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import threading

def my_func(num):
    return print('my_func calldeb by thread {}'.format(num))

def main():
    record =[]
	for i in range(10):
	     t = threading.Thread(target=my_func, args=(i,))
		 record.append(t)
		 t.start()
		 t.join()
if __name__ =="__main__"
     main()

多进程操作

多进程调用shell
import os
import sys
import multiprocessing

def process(n,cmd):
    print("Porcess num {} cmd={}".format(n,cmd))
    os.subprocess(cmd,shell=True)
def multi_process(file_list,i, cmd):
    record  = []
    process_num = len(file_list)
    for i in range(process_num):
        cmd = "touch " + file_list[i]
        p = multiprocessing.Process(target=process, args=(i, cmd))
        p.start()
        record.append(p)
    for p in record:
        p.join()

if __name__ == "__main__":
    file_list = ["a1.txt",'b1.txt','c1.txt','d.txt']
    multi_process(file_list,i, cmd)

multiprocessing.Pool 跨平台

####2.现象描述
     This probably means that you are not using fork to start your child processes
####原因
     multiprocessing.Pool创建进程池时,
	  Python在Windows系统下无法使用fork来创建进程。相反,它会使用spawn或forkserver来创建子进程,但是这种方式会导致某些全局变量在创建子进程时被重复创建,从而导致错误
		       Linux系统下,Python默认使用fork来创建进程
####解决方式
     使用multiprocessing.get_context()指定spawn或forkserver
         在创建进程池之前,我们可以使用multiprocessing.get_context()函数来获取进程上下文,并且根据需要使用spawn或forkserver来启动进程池。
		 使用get_context('spawn')显式地指定使用spawn来创建子进程
		import multiprocessing  
        def myfunc(x):
            return x*x
        
        if __name__ == '__main__':
            ctx = multiprocessing.get_context('spawn')
            with ctx.Pool(processes=4) as pool:
                result = pool.map(myfunc, range(10))
                print(result)
####拓展
    Python 多进程编程:创建进程的三种模式之spawn、fork、forkserver
      multiprocessing.get_all_start_methods():返回一个列表,包含了当前系统支持的所有启动方法,包括上述四种和其他系统特定的启动方法。
	    可以通过循环这个列表,尝试使用不同的启动方法创建进程,以寻找最合适的方式。
    spawn:从头构建一个子进程,父进程的数据等拷贝到子进程空间内,拥有自己的Python解释器,所以需要重新加载一遍父进程的包,
        因此启动较慢,由于数据都是自己的,安全性较高
fork:除了必要的启动资源外,其他变量,包,数据等都继承自父进程,并且是copy-on-write的,也就是共享了父进程的一些内存页,
    因此启动较快,但是由于大部分都用的父进程数据,所以是不安全的进程
例如:调用Flask的run方法,以多进程模型启动,会抛出“ValueError: Your platform does not support forking.”, 
   说明flask中的多进程默认使用 fork 模式,而windows系统并不支持此模式

参考

详解python中的Lock与RLock https://blog.csdn.net/lgyfhk/article/details/105254079
https://www.zhihu.com/question/37732728/answer/1079020249
posted @ 2021-07-22 18:15  辰令  阅读(241)  评论(0编辑  收藏  举报