python学习——进程

知识点回顾:

1. GIL锁
2. 进程和线程的区别?
  第一:
    进程是cpu资源分配的最小单元。
    线程是cpu计算的最小单元。
  第二:
    一个进程中可以有多个线程。
  第三:
    对于Python来说他的进程和线程和其他语言有差异,是有GIL锁。
    GIL锁保证一个进程中同一时刻只有一个线程被cpu调度。
注意:IO密集型操作可以使用多线程;计算密集型可以使用多进程;

3. Lock和RLock
  同步锁,递归锁
4. 线程池
  py2里没有,对多开启线程的个数,线程不是越多越好:线程之间的上下文切换浪费时间

5. threading.local
  为每一个线程开启一个空间,让线程存储数据

6. 面向对象补充:

class Foo(object):

    def __init__(self):
        object.__setattr__(self, 'info', {}) # 在对象中设置值的本质

    def __setattr__(self, key, value):
        self.info[key] = value

    def __getattr__(self, item):
        print(item)
        return self.info[item]

obj = Foo()
obj.name = 'alex'
print(obj.name)

本文主要内容:
1. 进程
2. 数据共享
3. 锁
4. 进程池
5. 模块(爬虫)
- requests
- bs4(beautifulsoup)
6. 协程

内容详细:
1. 进程
  - 进程间数据不共享

import multiprocessing

data_list = []
def task(arg):
    data_list.append(arg)
    print(data_list)

def run():
    for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,))
        p.start()

if __name__ == '__main__':
    run()

  - 常用功能:
    - join
    - deamon:True主进程运行完不等待子进程,False主进程运行完等待子进程
    - name
    - multiprocessing.current_process()获取当前进程
    - multiprocessing.current_process().ident/pid获取当前进程id

  - 类继承方式创建进程

import multiprocessing

class MyProcess(multiprocessing.Process):

    def run(self):
        print('当前进程',multiprocessing.current_process())

def run():
    p1 = MyProcess()
    p1.start()

  p2 = MyProcess()
  p2.start()

if __name__ == '__main__':
    run()

2. 进程间数据共享
  Queue:
    linux:

import multiprocessing
import queue
q = multiprocessing.Queue()

def task(arg,q):
    q.put(arg)


def run():
    for i in range(10):
        p = multiprocessing.Process(target=task, args=(i, q,))
        p.start()

    while True:
        v = q.get()
        print(v)
run()

  windows: 

import multiprocessing
import queue

def task(arg,q):
    q.put(arg)

if __name__ == '__main__':
    q = multiprocessing.Queue()
    for i in range(10):
        p = multiprocessing.Process(target=task,args=(i,q,))
        p.start()
    while True:
        v = q.get()
        print(v)

  Manager:(*)
    Linux:

import multiprocessing
import queue

m = multiprocessing.Manager()
dic = m.dict()

def task(arg):
    dic[arg] = 100

def run():
    for i in range(10):
        p = multiprocessing.Process(target=task, args=(i,))
        p.start()

input('>>>')
print(dic.values())

if __name__ == '__main__':
    run()

windows:

import multiprocessing
import queue

def task(arg,dic):
    time.sleep(2)
    dic[arg] = 100

if __name__ == '__main__':
    m = multiprocessing.Manager()
  dic = m.dict() process_list
= [] for i in range(10): p = multiprocessing.Process(target=task, args=(i,dic,)) p.start() process_list.append(p) while True: count = 0 for p in process_list: if not p.is_alive(): count += 1 if count == len(process_list): break print(dic)

3. 进程锁 (与线程一样)

不同进程/线程共用一个数据的时候需要枷锁

为什么要加锁?数据共享

import time
import threading
import multiprocessing

lock = multiprocessing.RLock()

def task(arg):
    print('鬼子来了')
    lock.acquire()
    time.sleep(2)
    print(arg)
    lock.release()

if __name__ == '__main__':
    p1 = multiprocessing.Process(target=task,args=(1,))
    p1.start()

    p2 = multiprocessing.Process(target=task, args=(2,))
    p2.start()

4. 进程池

import time
from concurrent.futures import ProcessPoolExecutor

def task(arg):
    time.sleep(2)
    print(arg)

if __name__ == '__main__':

    pool = ProcessPoolExecutor(5)
    for i in range(10):
        pool.submit(task,i)

5. 初识爬虫:
示例:

import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor


# 模拟浏览器发送请求
# 内部创建 sk = socket.socket()
# 和抽屉进行socket连接 sk.connect(...)
# sk.sendall('...')
# sk.recv(...)

def task(url):
    print(url)
    r1 = requests.get(
        url=url,
        headers={
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36'
        }
    )

    # 查看下载下来的文本信息
    soup = BeautifulSoup(r1.text,'html.parser')
    print(soup.text)
    content_list = soup.find('div',attrs={'id':'content-list'})#获取div节点下的content-list节点
    for item in content_list.find_all('div',attrs={'class':'item'}):
        title = item.find('a').text.strip()
        target_url = item.find('a').get('href')
        print(title,target_url)

def run():
    pool = ThreadPoolExecutor(5)
    for i in range(1,50):
        pool.submit(task,'https://dig.chouti.com/all/hot/recent/%s' %i)


if __name__ == '__main__':
    run()


相关:
  a. 以上爬虫示例进程和线程那个好?
    - 线程好——IO请求
  b. requests模块模拟浏览器发送请求
    - 本质 requests.get(...):
    - 创建socket客户端
    - 连接 【阻塞】
    - 发送请求
    - 接收请求【阻塞】
    - 断开连接
  c. 线程和进程池

原文地址:https://www.cnblogs.com/bilx/p/11460007.html