如何在python中多线程调用另一个端点方法?
我有一个带有两个端点的api,一个是接收json的简单post,另一个是根据json列表的长度多次调用第一个端点并将返回保存到列表的端点 第一种方法如何在python中多线程调用另一个端点方法?,python,multithreading,flask,cors,Python,Multithreading,Flask,Cors,我有一个带有两个端点的api,一个是接收json的简单post,另一个是根据json列表的长度多次调用第一个端点并将返回保存到列表的端点 第一种方法 @app.route('/getAudience', methods=['POST', 'OPTIONS']) def get_audience(audience_=None): try: if audience_: audience = audience_ else:
@app.route('/getAudience', methods=['POST', 'OPTIONS'])
def get_audience(audience_=None):
try:
if audience_:
audience = audience_
else:
audience = request.get_json()
except (BadRequest, ValueError):
return make_response(jsonify(exception_response), 500)
return get_audience_response(audience, exception_response)
第二种方法
@app.route('/getMultipleAudience', methods=['POST', 'OPTIONS'])
def get_multiple_audience():
try:
audiences = request.json
except (BadRequest, ValueError):
return make_response(jsonify(exception_response), 500)
response = []
for audience in audiences:
new_resp = json.loads(get_audience(audience).data)
response.append(new_resp)
return make_response(jsonify(response))
我想调用第一个方法,在第二个方法的列表中为每个对象启动一个线程,所以我尝试了以下方法:
def get_multiple_audience():
with app.app_context():
try:
audiences = request.get_json()
except (BadRequest, ValueError):
return make_response(jsonify(exception_response), 500)
for audience in audiences:
thread = Thread(target=get_audience, args=audience)
thread.start()
thread.join()
return make_response(jsonify(response))
得到了这个错误:
Exception in thread Thread-6:
Traceback (most recent call last):
File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\lib\threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "C:\Python27\lib\site-packages\flask_cors\decorator.py", line 123, in wrapped_function
options = get_cors_options(current_app, _options)
File "C:\Python27\lib\site-packages\flask_cors\core.py", line 286, in get_cors_options
options.update(get_app_kwarg_dict(appInstance))
File "C:\Python27\lib\site-packages\flask_cors\core.py", line 299, in get_app_kwarg_dict
app_config = getattr(app, 'config', {})
File "C:\Python27\lib\site-packages\werkzeug\local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "C:\Python27\lib\site-packages\werkzeug\local.py", line 306, in _get_current_object
return self.__local()
File "C:\Python27\lib\site-packages\flask\globals.py", line 51, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
然后我尝试修改第一种方法,如下所示:
@app.route('/getAudience', methods=['POST', 'OPTIONS'])
def get_audience(audience_=None):
with app.app_context():
try:
...
得到了同样的错误。有谁能给我一个提示、建议、最佳实践或解决方案吗?这里有很多问题。首先,这里:
for audience in audiences:
thread = Thread(target=get_audience, args=audience)
thread.start()
thread.join()
您只需要等待最后一个线程完成。您应该拥有所有线程的列表,并等待所有线程完成
threads = []
for audience in audiences:
thread = Thread(target=get_audience, args=audience)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
第二个问题是,您返回的是单个响应
,它甚至没有设置在任何位置。但多线程不是这样工作的。您将从所有线程获得多个结果,并且必须跟踪它们。因此,您可以创建一个results
数组来保存每个线程返回值的答案。这里我将做一个简单的函数sum
,作为一个例子
results = []
threads = []
def sum(a, b):
results.append(a + b)
@app.route("/test")
def test():
with app.app_context():
for i in range(5):
t = Thread(target=sum, args=(1, 2))
threads.append(t)
t.start()
for t in threads:
t.join()
return jsonify(results)
这将很好地工作,它将返回所有调用sum()
函数的结果
现在,如果我将总和更改为:
@app.route("/mysum/a/b")
def sum(a, b):
results.append(a + b)
return jsonify(a + b)
我将得到一个与前面得到的错误类似的错误:即,RuntimeError:在请求上下文之外工作。
,甚至认为返回值仍然正确:[3,3,3,3]
。这里发生的事情是,您的sum
函数现在正试图返回一个flash响应,但它驻留在自己的临时线程中,无法访问flash的任何内部上下文。您应该做的是永远不要在临时工作线程中返回值,而是使用一个池来存储它们以供将来参考
但这并不意味着你不能有一条/mysum
路线。的确,你可以,但逻辑必须分开。总而言之:
results = []
threads = []
def sum(a, b):
return a + b
def sum_worker(a, b):
results.append(sum(a, b))
@app.route("/mysum/a/b")
def mysum(a, b):
return jsonify(sum(a, b))
@app.route("/test")
def test():
with app.app_context():
for i in range(5):
t = Thread(target=sum_worker, args=(1, 2))
threads.append(t)
t.start()
for t in threads:
t.join()
return jsonify(results)
请注意,此代码非常粗糙,仅用于演示目的。我不建议在整个应用程序中使用全局变量,因此需要进行一些清理。如果要测试web服务,最好的方法是使用请求创建单独/独立的应用程序。