我正在为一个物联网应用程序的相机端点工作,我想启动并停止一个烧瓶应用程序,以显示带有流式摄像机数据的网页。我把所有单独的部件都工作了但是当我把它们放在一起时它就失败了。
如果我在启动另一个线程后启动一个烧瓶进程,它会抱怨该地址已被使用。这是一个精简的例子:
#!/usr/bin/env python3
import os
import threading
from flask import Flask
import socket
import time
from multiprocessing import Process
app = Flask(__name__)
def main():
start_thread(udp_listener)
start_process(runflask)
while True:
time.sleep(1)
def start_thread(function, arguments=()):
th = threading.Thread(target=function, args=arguments)
th.daemon = True
th.start()
def start_process(function):
server = Process(target=function)
server.start()
while True:
time.sleep(60)
server.terminate()
server.join()
def udp_listener():
while True:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.bind(('', 9000))
print('udp listening on port 9000')
while True:
data, server = s.recvfrom(4069)
print('received:')
def runflask():
app.run(host='0.0.0.0', port=8001, debug=True)
if __name__ == "__main__":
main()
注释掉start_thread()并运行start_process()即可。 注释掉start_process()并运行start_thread(),它就可以了。 即使他们正在不同的端口上侦听,也要运行这两个地址并获取一个已在使用中的地址错误。
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "./webcam_test.py", line 35, in udp_listener
s.bind(('', 9000))
OSError: [Errno 98] Address already in use
我想以一种让我按照命令启动和停止它的方式运行烧瓶应用程序。我应该采用不同的方式吗?
答案 0 :(得分:0)
我可以使用此处指定的ServerThread解决此问题:How to stop flask application without using ctrl-c
重要的是要注意调用此ServerThread会自动阻塞,因此如果您需要可中断的线程,则需要将其实例化为另一个线程的子节点。我的设计已经为每个摄像头模式生成了线程,所以现在我有一个线程调用线程调用线程:)。
我仍然不知道为什么烧瓶作为一个过程运行时会抱怨不相关的监听套接字,但现在我有一个解决方法。
答案 1 :(得分:0)
这仍然无关紧要,但是:
快速浏览一下,我看不到要绑定的套接字(s.bind(('', 9000))
)关闭的任何地方。由于它在循环中,因此它试图绑定再次使用的套接字,因此出错了吗?应该先停止它,然后再重新绑定:
s.shutdown(1)
s.close()
如果是这种情况,我建议的第一个解决方案是正确关闭套接字,而不要在循环中启动它(为什么首先将套接字绑定在循环中?)
如果仅此操作无济于事,请允许套接字重用地址:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)