当前位置:   article > 正文

python 多进程 requests_python requests多进程不安全的场景

python requests线程安全问题

python requests是个老牌的http client库,在多线程下(threading)是安全的,在协程下自然也是安全的。值得一说的是Requets自身并没有实现连接池,而是引入了标准库urllib2的连接池。池的线程安全实现很简单,就是加锁控制边界。

既然是requests是线程安全的,那么在多进程下是否安全? 是否安全需要看你如何去使用multiprocessing requests了。如果是先fork子进程再进行http请求,那么是没有问题的。如果是先使用了session连接池,再去fork子进程,那么会出现多进程下socket读写不安全的问题。

requests默认有一个session对象,该session对象会绑定一个连接池。当你在fork子进程前,先请求了一个api,那么产生的socket连接会保留在session对象里。这时候你fork了子进程,子进程不仅继承父进程空间,而且会继承文件描述符。当再次尝试请求http请求时,有可能出现多个进程对一个连接进行写入和读取。

import time

import requests

from multiprocessing import Process, Queue

uri = 'http://www.163.com'

q = Queue()

session = requests.Session()

def req(args):

while 1:

response = session.get(uri)

print(response)

time.sleep(3)

def feed():

q.put("sss")

if __name__ == '__main__':

response = session.get(uri)

pids = []

for num in range(5):

p = Process(target=req, args=(11, ))

p.start()

pids.append(p)

for pid in pids:

pid.join()

我们会发现不同pid的进程往同一个文件描述符去读写数据,这个就是requests session非进程安全的表现了。

那么如何解决这个问题呢?python多进程下不要共用同一个requests session,或者说不要共用一个存有连接对象的session对象。

个人觉得python那么多网络库的连接池安全方面,redis-py做的就很好,redis py会通过pid来判断连接池对象是否从父进程继承的,如是继承则重新实例化新的连接池对象。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/172605
推荐阅读
相关标签
  

闽ICP备14008679号