gpt4 book ai didi

Python如何停止线程操作

转载 作者:太空宇宙 更新时间:2023-11-03 15:23:27 24 4
gpt4 key购买 nike

我想知道如何使用 CTRL+C 或类似的东西在控制台中停止我的程序。问题是我的程序中有两个线程。线程一抓取网络并提取一些数据,线程二以用户可读的格式显示此数据。两个部分共享同一个数据库。我这样运行它们:

from threading import Thread
import ResultsPresenter

def runSpider():
Thread(target=initSpider).start()
Thread(target=ResultsPresenter.runPresenter).start()


if __name__ == "__main__":
runSpider()

我该怎么做?

好的,所以我创建了自己的线程类:

import threading

class MyThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""

def __init__(self):
super(MyThread, self).__init__()
self._stop = threading.Event()

def stop(self):
self._stop.set()

def stopped(self):
return self._stop.isSet()

好的,我将在此处发布 resultPresenter 和爬虫的片段。这是 resultPresenter 的代码:

# configuration
DEBUG = False
DATABASE = database.__path__[0] + '/database.db'

app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('CRAWLER_SETTINGS', silent=True)

def runPresenter():
url = "http://127.0.0.1:5000"
webbrowser.open_new(url)
app.run()

这里还有两个方法我省略了——一个连接数据库,第二个方法加载html模板显示结果。我重复这个直到满足条件或用户停止程序(我正在尝试实现的)。还有其他两种方法 - 一种是从命令行获取初始链接,另一种是验证参数 - 如果参数无效,我将不会运行 crawl() 方法。

这是爬虫的简短版本:

def crawl(initialLink, maxDepth):
#here I am setting initial values, lists etc

while not(depth >= maxDepth or len(pagesToCrawl) <= 0):

#this is the main loop that stops when certain depth is
#reached or there is nothing to crawl
#Here I am popping urls from url queue, parse them and
#insert interesting data into the database


parser.close()
sock.close()
dataManager.closeConnection()

这是在线程中启动这些模块的 init 文件:

import ResultsPresenter, MyThread, time, threading

def runSpider():

MyThread.MyThread(target=initSpider).start()
MyThread.MyThread(target=ResultsPresenter.runPresenter).start()


def initSpider():

import Crawler
import database.__init__
import schemas.__init__
import static.__init__
import templates.__init__

link, maxDepth = Crawler.getInitialLink()
if link:
Crawler.crawl(link, maxDepth)



killall = False

if __name__ == "__main__":

global killall
runSpider()

while True:

try:
time.sleep(1)

except:

for thread in threading.enumerate():
thread.stop()

killall = True
raise

最佳答案

杀死线程不是一个好主意,因为(正如您已经说过的)它们可能正在对数据库执行一些关键操作。因此,您可以定义全局标志,这将向线程发出信号,表明它们应该完成它们正在做的事情并退出。

killall = False

import time
if __name__ == "__main__":
global killall
runSpider()
while True:
try:
time.sleep(1)
except:
/* send a signal to threads, for example: */
killall = True
raise

并且在每个线程中,您都在一个类似的循环中检查 killall 变量是否设置为 True。如果它关闭所有事件并退出线程。

编辑

首先:异常是相当明显的。您正在将 target 参数传递给 __init__,但您没有在 __init__ 中声明它。这样做:

class MyThread(threading.Thread):

def __init__(self, *args, **kwargs):
super(MyThread, self).__init__(*args, **kwargs)
self._stop = threading.Event()

其次:您没有使用我的代码。正如我所说:设置标志并在线程中检查它。当我说“线程”时,我实际上是指处理程序,即 ResultsPresenter.runPresenterinitSpide。向我们展示其中之一的代码,我将尝试向您展示如何处理停止。

编辑 2

假设crawl函数的代码在同一个文件中(如果不是,那么你必须导入killall变量),你可以这样做

def crawl(initialLink, maxDepth):
global killall
# Initialization.
while not killall and not(depth >= maxDepth or len(pagesToCrawl) <= 0):
# note the killall variable in while loop!
# the other code
parser.close()
sock.close()
dataManager.closeConnection()

所以基本上你只是说:“嘿,线程,现在退出循环!”。您可以选择从字面上打破循环:

while not(depth >= maxDepth or len(pagesToCrawl) <= 0):
# some code
if killall:
break

当然它仍然需要一些时间才能退出(必须完成循环并关闭解析器、套接字等),但它应该安全退出。至少这是个想法。

关于Python如何停止线程操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11185158/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com