[英]Can't quit Python script with Ctrl-C if a thread ran webbrowser.open()
我正在使用Python的Bottle Web應用程序框架( pip install bottle
),並希望運行一個可以從本地計算機訪問的Web應用程序(本質上是一個使用GUI瀏覽器的桌面應用程序)。 要啟動bottle Web應用程序,我必須調用bottle.run()
但是只要腳本正在運行,它就會一直阻塞。 您可以通過按Ctrl-C停止它。
但是,我也希望該應用通過調用webbrowser.open()
將網絡瀏覽器打開到localhost。 問題是,我不能先調用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應用程序。 我不確定為什么會這樣: 'Browser opened'
被打印到屏幕上,所以我知道webbrowser.open()
正在返回。
我在Windows 7上。
我已經嘗試self._running = False
如何終止在設置self._running = False
python中調用webbrowser的線程的解決方案,但這並沒有改變任何東西。 我可以從中調用join()
的線程之外也沒有地方。
即使我擺脫了單獨的線程並使用os.system('python openbrowser.py')
運行了等待一秒鍾並打開os.system('python openbrowser.py')
瀏覽器的腳本,這仍然會阻止Ctrl-C正常工作。
我也嘗試使用threading.Timer(1, webbrowser.open, ['http://localhost:8042']).start()
啟動瀏覽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()
您可能需要為實際應用程序進行相當大的修改,但是希望它可以幫助您入門。 祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.