Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gevent greenlets之间是否共享Python请求会话对象,线程安全(greenlets之间)?_Python_Python 2.7_Thread Safety_Python Requests_Gevent - Fatal编程技术网

gevent greenlets之间是否共享Python请求会话对象,线程安全(greenlets之间)?

gevent greenlets之间是否共享Python请求会话对象,线程安全(greenlets之间)?,python,python-2.7,thread-safety,python-requests,gevent,Python,Python 2.7,Thread Safety,Python Requests,Gevent,在gevented程序中,库会话对象能否安全地跨Greenlet使用 编辑-添加更多解释: 当一个greenlet因为发出套接字调用以向服务器发送请求而让步时,另一个greenlet是否可以安全地使用同一套接字(在共享会话对象内)来发送自己的请求 结束编辑 我试图用这里发布的代码来测试这一点——但是我没有得到任何错误或意外的结果。但是,这并不验证线程安全性 在测试中,我使用一个共享会话对象发出大量请求,并尝试查看该对象是否将请求弄混了——这有点幼稚,但我没有发现任何异常 为方便起见,我在此处重新

在gevented程序中,库会话对象能否安全地跨Greenlet使用

编辑-添加更多解释:

当一个greenlet因为发出套接字调用以向服务器发送请求而让步时,另一个greenlet是否可以安全地使用同一套接字(在共享会话对象内)来发送自己的请求

结束编辑

我试图用这里发布的代码来测试这一点——但是我没有得到任何错误或意外的结果。但是,这并不验证线程安全性

在测试中,我使用一个共享会话对象发出大量请求,并尝试查看该对象是否将请求弄混了——这有点幼稚,但我没有发现任何异常

为方便起见,我在此处重新粘贴代码:

client.py

import gevent
from gevent.monkey import patch_all
patch_all()

import requests
import json

s = requests.Session()

def make_request(s, d):
    r = s.post("http://127.0.0.1:5000", data=json.dumps({'value': d}))
    if r.content.strip() != str(d*2):
        print("Sent %s got %s" % (r.content, str(d*2)))
    if r.status_code != 200:
        print(r.status_code)
        print(r.content)

gevent.joinall([
    gevent.spawn(make_request, s, v)
    for v in range(300)
])
from gevent.wsgi import WSGIServer
from gevent.monkey import patch_all

patch_all()

from flask import Flask
from flask import request

import time
import json

app = Flask(__name__)

@app.route('/', methods=['POST', 'GET'])
def hello_world():
    d = json.loads(request.data)
    return str(d['value']*2)

if __name__ == '__main__':
    http_server = WSGIServer(('', 5000), app)
    http_server.serve_forever()
server.py

import gevent
from gevent.monkey import patch_all
patch_all()

import requests
import json

s = requests.Session()

def make_request(s, d):
    r = s.post("http://127.0.0.1:5000", data=json.dumps({'value': d}))
    if r.content.strip() != str(d*2):
        print("Sent %s got %s" % (r.content, str(d*2)))
    if r.status_code != 200:
        print(r.status_code)
        print(r.content)

gevent.joinall([
    gevent.spawn(make_request, s, v)
    for v in range(300)
])
from gevent.wsgi import WSGIServer
from gevent.monkey import patch_all

patch_all()

from flask import Flask
from flask import request

import time
import json

app = Flask(__name__)

@app.route('/', methods=['POST', 'GET'])
def hello_world():
    d = json.loads(request.data)
    return str(d['value']*2)

if __name__ == '__main__':
    http_server = WSGIServer(('', 5000), app)
    http_server.serve_forever()
确切的库版本:

requirements.txt

Flask==0.10.1
Jinja2==2.7.2
MarkupSafe==0.23
Werkzeug==0.9.4
argparse==1.2.1
gevent==1.0.1
greenlet==0.4.2
gunicorn==18.0
itsdangerous==0.24
requests==2.3.0
wsgiref==0.1.2

是否有其他测试可以检查greenlet线程的安全性?请求文档在这一点上不太清楚。

请求的作者也创建了一个
gevent
-integration包:。用它来代替

它支持使用
session
关键字传入会话:

import grequests

s = requests.Session()

requests = [grequests.post("http://127.0.0.1:5000", 
                           data=json.dumps({'value': d}), session=s)
            for d in range(300)]

responses = grequests.map(requests)
for r in responses:
    if r.content.strip() != str(d*2):
        print("Sent %s got %s" % (r.content, str(d*2)))
    if r.status_code != 200:
        print(r.status_code)
        print(r.content)

请记住,greenlet不会在单独的线程中运行。该代码运行在您声明的同一线程(即主线程)上,我将编辑该问题-但我的意思是会话对象是否是greenlet安全的?当一个greenlet在通过套接字发送内容时让步时,另一个greenlet是否可以抓住同一个套接字(在会话对象内部)并发送它自己的内容?底层套接字(如果是标准的话)只有一个执行流AFAIK,而不能同时访问。至少在标准C impl中是这样的。会话对象不是套接字或连接对象上的包装器,而是套接字/连接池上的包装器。如果没有可重用的连接,此连接池将为新的greenlet创建新连接。在我的实际应用程序中,我将无法收集所有请求并使用map调用。使用共享会话对象在不同的Greenlet中发出请求。这就是我想确认线程安全的原因。@donatello:map调用使用自己的池,您可以设置自己的池并向其中添加要执行的请求。@donatello:use
grequests.send()
使用自己的池发送请求,请参见示例。greenlet只有在产生时才被抢占;这里的I/O是自动生成的。但是在会话中处理共享状态的代码不会被抢占,因此不会受到竞争条件的影响;连接由线程安全的连接池处理(受
threading.RLock
保护)。