Flask:如果我计算请求我不能做多线程
Flask: if I count requests I can't do multithreading
我有一个 Flask API 应该收到请求,用 selenium 做一些事情,然后 return 给用户一些事情。
版本 1
import flask
from multiprocessing import Value
from selenium import webdriver
app = flask.Flask(__name__)
app.config["DEBUG"] = False
@app.route('/api/url', methods=['GET', 'POST'])
def site():
# do some stuff ...
with open(os.path.normpath(os.getcwd() + "\file.mp3"), 'wb') as f:
f.write(<something>)
# ... do some other stuff and return a variable
def home():
return "<h1>Distant Reading Archive</h1><p>This site is a prototype API for distant reading of science fiction novels.</p>"
app.run(host="0.0.0.0", threaded=True)
这段代码在技术上可以完美运行,如果不是我需要同时管理多个请求:例如,如果我同时处理两个请求,第二个请求将覆盖file 在第一个请求创建的文件上,这将是一个问题。
版本 2
为了避免所有线程都覆盖同一个文件,我通过包含 counter
变量来更改代码,该变量充当请求计数器(来自此答案 )。
以下代码将为每个请求创建一个名为 file<n>.mp3
的文件,其中 <n>
是请求的编号(第 <n>
个请求),因此我将每个请求都有不同的文件。
import flask
from multiprocessing import Value
from selenium import webdriver
app = flask.Flask(__name__)
app.config["DEBUG"] = False
@app.route('/api/url', methods=['GET', 'POST'])
counter = Value('i', 0)
def site():
with counter.get_lock():
counter.value += 1
out = counter.value
# do some stuff ...
with open(os.path.normpath(os.getcwd() + "\file{}.mp3".format(out)), 'wb') as f:
f.write(<something>)
# ... do some other stuff and return a variable
def home():
return "<h1>Distant Reading Archive</h1><p>This site is a prototype API for distant reading of science fiction novels.</p>"
app.run(host="0.0.0.0", threaded=True)
版本 2 有问题
代码版本 2 的问题是多线程显然停止工作,代码一次只处理一个请求。
多线程停止工作的事实似乎与我包含计数器的事实有关,因为在版本 1 中多线程确实工作并且 API 分别处理所有不同的请求(但代码仍然没有由于覆盖问题,我的行为就像我想要的那样)
问题
我如何计算所有请求并仍然设法在其 own/with 其文件中处理每个请求,同时同时处理多个请求?
问题是 with counter.get_lock()
中包含了太多代码。只要你有这个锁,其他线程就不能运行.
相反你想要:
with counter.get_lock():
counter.value += 1
out = counter.value
do rest of the stuff outside of the lock
我有一个 Flask API 应该收到请求,用 selenium 做一些事情,然后 return 给用户一些事情。
版本 1
import flask
from multiprocessing import Value
from selenium import webdriver
app = flask.Flask(__name__)
app.config["DEBUG"] = False
@app.route('/api/url', methods=['GET', 'POST'])
def site():
# do some stuff ...
with open(os.path.normpath(os.getcwd() + "\file.mp3"), 'wb') as f:
f.write(<something>)
# ... do some other stuff and return a variable
def home():
return "<h1>Distant Reading Archive</h1><p>This site is a prototype API for distant reading of science fiction novels.</p>"
app.run(host="0.0.0.0", threaded=True)
这段代码在技术上可以完美运行,如果不是我需要同时管理多个请求:例如,如果我同时处理两个请求,第二个请求将覆盖file 在第一个请求创建的文件上,这将是一个问题。
版本 2
为了避免所有线程都覆盖同一个文件,我通过包含 counter
变量来更改代码,该变量充当请求计数器(来自此答案
以下代码将为每个请求创建一个名为 file<n>.mp3
的文件,其中 <n>
是请求的编号(第 <n>
个请求),因此我将每个请求都有不同的文件。
import flask
from multiprocessing import Value
from selenium import webdriver
app = flask.Flask(__name__)
app.config["DEBUG"] = False
@app.route('/api/url', methods=['GET', 'POST'])
counter = Value('i', 0)
def site():
with counter.get_lock():
counter.value += 1
out = counter.value
# do some stuff ...
with open(os.path.normpath(os.getcwd() + "\file{}.mp3".format(out)), 'wb') as f:
f.write(<something>)
# ... do some other stuff and return a variable
def home():
return "<h1>Distant Reading Archive</h1><p>This site is a prototype API for distant reading of science fiction novels.</p>"
app.run(host="0.0.0.0", threaded=True)
版本 2 有问题
代码版本 2 的问题是多线程显然停止工作,代码一次只处理一个请求。
多线程停止工作的事实似乎与我包含计数器的事实有关,因为在版本 1 中多线程确实工作并且 API 分别处理所有不同的请求(但代码仍然没有由于覆盖问题,我的行为就像我想要的那样)
问题
我如何计算所有请求并仍然设法在其 own/with 其文件中处理每个请求,同时同时处理多个请求?
问题是 with counter.get_lock()
中包含了太多代码。只要你有这个锁,其他线程就不能运行.
相反你想要:
with counter.get_lock():
counter.value += 1
out = counter.value
do rest of the stuff outside of the lock