使用 Flask 中的路由控制守护线程
control a daemon thread with routes in flask
如何在 python
中让两个路由控制一个守护线程
flask 后端文件
from flask import Flask
from time import time,sleep
from threading import Thread
app = Flask(__name__)
def intro():
while True:
sleep(3)
print (f" Current time : {time()}")
@app.route('/startbot')
def start_bot():
global bot_thread
bot_thread = Thread(target=intro, daemon=True)
bot_thread.start()
return "bot started "
@app.route('/stopbot')
def stop_bot():
bot_thread.join()
return
if __name__ == "__main__":
app.run()
当试图终止线程时,终端中的 curl 请求不会 return 返回控制台并且线程继续向终端打印数据
我的想法是声明保存对 bot_thread 的引用的变量并使用路由来控制它
为了测试这一点,我使用了 curl http://localhost:port/startbot
和 curl http://localhost:port/stopbot
我可以很好地启动机器人,但是当我试图杀死它时,我得到以下信息
NameError: name 'bot_thread' is not defined
我们将不胜感激任何帮助和注意事项
考虑到在终止线程后,用户可以创建一个新线程,也可以终止它
这是一个 Minimal Reproducible Example :
from threading import Thread
def intro():
print("hello")
global bot_thread
def start_bot():
bot_thread = Thread(target=intro, daemon=True)
return
def stop_bot():
if bot_thread:
bot_thread.join()
if __name__ == "__main__":
import time
start_bot() # simulating a request on it
time.sleep(1) # some time passes ...
stop_bot() # simulating a request on it
Traceback (most recent call last):
File "/home/stack_overflow/so71056246.py", line 25, in <module>
stop_bot() # simulating a request on it
File "/home/stack_overflow/so71056246.py", line 17, in stop_bot
if bot_thread:
NameError: name 'bot_thread' is not defined
例如我的IDE makes the error visually clear for me : the bot_thread
is not used, because it is a local variable, not the global
one, although they have the same name. This is a pitfall for Python programmers, see this question or this one。
所以 :
def start_bot():
global bot_thread
bot_thread = Thread(target=intro, daemon=True)
return
但是
Traceback (most recent call last):
File "/home/stack_overflow/so71056246.py", line 26, in <module>
stop_bot() # simulating a request on it
File "/home/stack_overflow/so71056246.py", line 19, in stop_bot
bot_thread.join()
File "/usr/lib/python3.9/threading.py", line 1048, in join
raise RuntimeError("cannot join thread before it is started")
RuntimeError: cannot join thread before it is started
因此:
def start_bot():
global bot_thread
bot_thread = Thread(target=intro, daemon=True)
bot_thread.start()
return
最终给出:
hello
编辑
When trying to kill the thread the curl request in the terminal does not return back to the console and the thread keeps on printing data to the terminal
@prometheus bot_thread
运行 intro
函数。因为它包含一个无限循环 (while True
),它永远不会到达函数的末尾(隐式 return
),所以线程永远不会被视为已完成。正因为如此,当主线程尝试join
(等到线程完成,然后得到结果)时,它会无休止地等待,因为bot线程卡在了循环中。
所以你必须让退出 while
循环成为可能。例如(就像我在评论中链接的示例),通过使用另一个 global
变量,一个 flag,它在主线程(路由 stop_bot
)中设置并被选中在 intro
循环中。像这样:
from time import time, sleep
from threading import Thread
def intro():
global the_bot_should_continue_running
while the_bot_should_continue_running:
print(time())
sleep(1)
global bot_thread
global the_bot_should_continue_running
def start_bot():
global bot_thread, the_bot_should_continue_running
bot_thread = Thread(target=intro, daemon=True)
the_bot_should_continue_running = True # before the `start` !
bot_thread.start()
return
def stop_bot():
if bot_thread:
global the_bot_should_continue_running
the_bot_should_continue_running = False
bot_thread.join()
if __name__ == "__main__":
start_bot() # simulating a request on it
sleep(5.5) # some time passes ...
stop_bot() # simulating a request on it
打印 6 次然后退出。
如何在 python
中让两个路由控制一个守护线程flask 后端文件
from flask import Flask
from time import time,sleep
from threading import Thread
app = Flask(__name__)
def intro():
while True:
sleep(3)
print (f" Current time : {time()}")
@app.route('/startbot')
def start_bot():
global bot_thread
bot_thread = Thread(target=intro, daemon=True)
bot_thread.start()
return "bot started "
@app.route('/stopbot')
def stop_bot():
bot_thread.join()
return
if __name__ == "__main__":
app.run()
当试图终止线程时,终端中的 curl 请求不会 return 返回控制台并且线程继续向终端打印数据
我的想法是声明保存对 bot_thread 的引用的变量并使用路由来控制它
为了测试这一点,我使用了 curl http://localhost:port/startbot
和 curl http://localhost:port/stopbot
我可以很好地启动机器人,但是当我试图杀死它时,我得到以下信息
NameError: name 'bot_thread' is not defined
我们将不胜感激任何帮助和注意事项
考虑到在终止线程后,用户可以创建一个新线程,也可以终止它
这是一个 Minimal Reproducible Example :
from threading import Thread
def intro():
print("hello")
global bot_thread
def start_bot():
bot_thread = Thread(target=intro, daemon=True)
return
def stop_bot():
if bot_thread:
bot_thread.join()
if __name__ == "__main__":
import time
start_bot() # simulating a request on it
time.sleep(1) # some time passes ...
stop_bot() # simulating a request on it
Traceback (most recent call last):
File "/home/stack_overflow/so71056246.py", line 25, in <module>
stop_bot() # simulating a request on it
File "/home/stack_overflow/so71056246.py", line 17, in stop_bot
if bot_thread:
NameError: name 'bot_thread' is not defined
例如我的IDE makes the error visually clear for me : the bot_thread
is not used, because it is a local variable, not the global
one, although they have the same name. This is a pitfall for Python programmers, see this question or this one。
所以 :
def start_bot():
global bot_thread
bot_thread = Thread(target=intro, daemon=True)
return
但是
Traceback (most recent call last):
File "/home/stack_overflow/so71056246.py", line 26, in <module>
stop_bot() # simulating a request on it
File "/home/stack_overflow/so71056246.py", line 19, in stop_bot
bot_thread.join()
File "/usr/lib/python3.9/threading.py", line 1048, in join
raise RuntimeError("cannot join thread before it is started")
RuntimeError: cannot join thread before it is started
因此:
def start_bot():
global bot_thread
bot_thread = Thread(target=intro, daemon=True)
bot_thread.start()
return
最终给出:
hello
编辑
When trying to kill the thread the curl request in the terminal does not return back to the console and the thread keeps on printing data to the terminal
@prometheus bot_thread
运行 intro
函数。因为它包含一个无限循环 (while True
),它永远不会到达函数的末尾(隐式 return
),所以线程永远不会被视为已完成。正因为如此,当主线程尝试join
(等到线程完成,然后得到结果)时,它会无休止地等待,因为bot线程卡在了循环中。
所以你必须让退出 while
循环成为可能。例如(就像我在评论中链接的示例),通过使用另一个 global
变量,一个 flag,它在主线程(路由 stop_bot
)中设置并被选中在 intro
循环中。像这样:
from time import time, sleep
from threading import Thread
def intro():
global the_bot_should_continue_running
while the_bot_should_continue_running:
print(time())
sleep(1)
global bot_thread
global the_bot_should_continue_running
def start_bot():
global bot_thread, the_bot_should_continue_running
bot_thread = Thread(target=intro, daemon=True)
the_bot_should_continue_running = True # before the `start` !
bot_thread.start()
return
def stop_bot():
if bot_thread:
global the_bot_should_continue_running
the_bot_should_continue_running = False
bot_thread.join()
if __name__ == "__main__":
start_bot() # simulating a request on it
sleep(5.5) # some time passes ...
stop_bot() # simulating a request on it
打印 6 次然后退出。