如果线程运行webbrowser.open(),则无法使用Ctrl-C退出Python脚本
我正在使用用于
Python的Bottle Web应用程序框架(pip安装瓶),并希望运行一个只能从本地计算机访问的Web应用程序(它本质上是一个使用GUI浏览器的桌面应用程序).要启动瓶子web应用程序,我必须调用bottle.run(),但只要脚本正在运行,这就会阻塞.按Ctrl-C停止它.
但是,我也希望这个应用程序通过调用webbrowser.open()打开到localhost的Web浏览器.问题是,我不能先调用webbrowser.open()因为web应用程序不会运行,但如果我先调用bottle.run(),只要Web应用程序运行,它就不会返回无法继续调用webbrowser.open(). 我的解决方案是将调用webbrowser.open()放在一个线程中: import bottle import threading import webbrowser import time class BrowserOpener(threading.Thread): def run(self): time.sleep(1) # waiting 1 sec is a hack,but it works webbrowser.open('http://localhost:8042') print('Browser opened') @bottle.route('/') def index(): return 'hello world!' BrowserOpener().start() bottle.run(host='localhost',port=8042) 这个问题现在按下终端中的Ctrl-C似乎不起作用,所以除了完全关闭终端之外我无法停止Web应用程序.我不知道为什么会这样:’浏览器打开’被打印到屏幕上,所以我知道webbrowser.open()正在返回. 我在Windows 7上. 我已经尝试过设置self._running = False的how to terminate a thread which calls the webbrowser in python解决方案,但这并没有改变任何东西.在线程之外也没有我可以调用join()的地方. 即使我摆脱了单独的线程并使用os.system(‘python openbrowser.py’)来运行等待一秒的脚本并打开webbrowser,这仍然会阻止Ctrl-C工作. 我还尝试使用threading.Timer(1,webbrowser.open,[‘http:// localhost:8042’]).start()启动浏览器,但这仍然阻止了Ctrl-C的工作. 有没有我没见过的解决方案? 解决方法
这个答案有两个直接警告:
>可能有一种方法可以完成您想要的更接近原始设计的方法.如果你不想偏离原来的想法,也许另一个回答者可以提供更好的解决方案. 除此之外: 您可能会发现通过将服务器放在单独的线程中然后通过一些简单的信号从主(非阻塞)线程控制它,您可以更轻松地进行操作. import ctypes import threading import webbrowser import bottle class SimpleExampleApp(): def __init__(self): self.app = bottle.Bottle() #define all of the routes for your app inside the init method @self.app.get('/') def index(): return 'It works!' @self.app.get('/other_route') def alternative(): return 'This Works Too' def run(self): self.start_server_thread() #depending upon how much configuration you are doing #when you start the server you may need to add a brief #delay before opening the browser to make sure that it #is ready to receive the initial request webbrowser.open('http://localhost:8042') def start_server_thread(self): self.server_thread = threading.Thread( target = self.app.run,kwargs = {'host': 'localhost','port': 8042} ) self.server_thread.start() def stop_server_thread(self): stop = ctypes.pythonapi.PyThreadState_SetAsyncExc( ctypes.c_long(self.server_thread.get_ident()),ctypes.py_object(KeyboardInterrupt) ) #adding a print statement for debugging purposes since I #do not know how well this will work on Windows platform print('Return value of stop was {0}'.format(stop)) self.server_thread.join() my_app = SimpleExampleApp() my_app.run() #when you're ready to stop the app,simply call #my_app.stop_server_thread() 出于实际应用的目的,您可能需要对此进行相当大的修改,但它应该可以帮助您入门.祝好运! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |