Python并发编程

并发执行-并发编程

1.物理机

01.Windows
  NumberOfCores
  NumberOfLogicalProcessors
  
  cpu个数   是指物理上安装了几个cpu,一般的个人电脑是安装了1个cpu
  cpu内核数 是指物理上,一个cpu芯片上集成了几个内核单元,现代cpu都是多核的。
  cpu线程数 是指逻辑上处理单元,这个技术是Intel的超线程技术,它让操作系统识别到有多个处理单元
  
02.Linux服务器
 -- 正在运行的程序都会在/proc
 CPU的信息
     cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
     # 查看物理CPU个数
      cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
     # 查看每个物理CPU中core的个数(即核数)
      cat /proc/cpuinfo| grep "cpu cores"| uniq
     # 查看逻辑CPU的个数
	 cat /proc/cpuinfo| grep "processor"| wc -l
 内存
     cat /proc/meminfo
	 free -h 

 硬盘
     df  -h    说明:  Disk free  空余硬盘
     du  -sh           Disk usage 硬盘使用率
	  
 网络:
    ifconfig 

 内核模块
 
 驱动模块
  
etcetera 等等
twm = twm = Tom's Window Manager  

2.Python物理机和Python关系

1.物理机的情况
   多线程指的是,在一个进程中开启多个线程
   进程(process)  线程(thread)
   多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享	
   Python的线程虽然是真正的线程,但解释器执行代码时,
     有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁
     所有线程共享进程的内存
   可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。
   多核CPU上,可以运行多个进程(数量与CPU核心数相同),充分利用多核CPU
   Python语言,单线程的异步编程模型称为协程
2.CPU密集型 vs IO密集型
   CPU密集代码的执行中,多线程性能不如多进程
   多线程对IO密集型代码比较友好
    CPU密集型代码(各种循环处理、计数等等),推荐 多进程 - process
    I/O密集型代码(文件处理、网络爬虫等),  推荐 多线程 - thread

3.情况
  Queue Queue的作用是用来传递任务和接收结果
  对于多进程,GIL就无法限制,多个进程可以再多个CPU上运行,充分利用多核优势 
  
额外:
   协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine
   协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
   yield(生成器)可以很容易的实现上述的功能,从一个函数切换到另外一个函数
 异步编程asyncio库: python中使用协程最常用的库就是asyncio

3.Python3 通过标准库

本质: 切换+保存状态
进程+线程+协程
1.线程和进程
   threading 和  multiprocessing
   01.线程
    _thread 和 threading 提供对线程的支持
   其中 threading.currentThread() 
   在python中有GIL,线程锁,保证只有一个线程在计算,在不停的切换  
   python的线程属于内核级别的,即由操作系统控制调度
  02.进程
   需要mutliprocessing 因为每个核有单独的逻辑空间,互相不影响   
   每个进程都有自己独立的GIL
2.线程池和进程池
  ThreadPoolExecutor  异步调用的 线程池 的Executor
  ProcessPoolExecutor 异步调用的 进程池 的Executor
  01.线程池:
   ThreadPoolExecutor线程池
   
  02.进程池: 
   ProcessPoolExecutor 进程池,与 multiprocessing 标准的多进程模块。
    其实ProcessPoolExecutor也是对multiprocessing的封装调用,而multiprocessing则更加底层
	
 Queue用于建立和操作队列,常和threading类一起用来建立一个简单的线程队列		
 		
 Executor 对象  (map  submit  shutdown)
    ThreadPoolExecutor    是 Executor 的子类,它使用线程池来异步执行调用
       ThreadPoolExecutor.map
       ThreadPoolExecutor.submit
    ProcessPoolExecutor 类是 Executor 的子类,它使用进程池来异步地执行调用。
         ProcessPoolExecutor 会使用 multiprocessing 模块,这允许它绕过 全局解释器锁 但也意味着只可以处理和返回可封存的对象
 		
     map返回一个迭代器,其中的回调函数的参数 最好是可以迭代的数据类型,
     如list;如果有 多个参数 则 多个参数的 数据长度相同;
     如: pool.map(work,[[1,2],[3,4]],[0,1]]) 中 [1,2]对应0 ;[3,4]对应1 ;
      其实内部执行的函数为 work([1,2],0) ; work([3,4],1)
     map返回的结果是有序结果;是根据迭代函数执行顺序返回的结果
     使用map的优点是 每次调用回调函数的结果不用手动的放入结果list中
   
      pool.submit()
 		 submit方法提交可回调的函数,并返回一个future实例;
 		 future对象包含相关属性((cancel  cancelled  done  running  exception))
          例如: Future对象有一个done()方法,判断该Future是否己完成
 		 方法 执行数据的结果是无序的
 
 Future 类将可调用对象封装为异步执行。
    Future 实例由 Executor.submit() 创建
          
Linux 
   ps aux
   top
   pstree -aup   display a tree of processes
   
 对应的进程ID就可以查看到该进程打开的线程数
  service  job   Process  thread

4.Python执行系统命令-子进程

os
   os.system(cmd)的返回值是脚本的退出状态码,只会有0(成功),1,同时执行后结果直接打印在控制台,无法读取保存到文件&变量
   os.popen(cmd)返回脚本执行的输出内容作为返回值。执行后不会打印到控制台,可通过read()读取结果

subprocess 
    os.system可以用 subprocess.call来替代,
    os.popen可以使用subprocess.Popen来替代

带参数

# R语言	
apply(X, MARGIN, FUN, ...) FUN: 自定义的调用函数
b <- matrix(1:6,nrow=3)
myfun <- function(x){sum(x^2)}
apply(b,1,myfun)

aa <- matrix(1:9,3)
myfun <- function(x,y){ x**y}
apply(aa,1,myfun,y=3)

#Python
if __name__ == "__main__":
    num_list = [1, 2, 3, 4, 5]
    dat = [3 for i in range(len(num_list))]
    result = map(square, num_list,dat)
    for data in result:
        print(data)
原文地址:https://www.cnblogs.com/ytwang/p/14680451.html