Python线程测试无效
编辑
我通过创建进程来解决这个问题,而不是使用线程。从评论和评论中的链接来看,我觉得在这里使用线程并不是正确的选择。
感谢大家的帮助。
编辑完毕
我之前对线程的了解不多。我只写过几个简单的“你好,世界”脚本,但没有做过实际的工作。
为了帮助我理解线程,我写了一个简单的脚本,使用Nagios的二进制文件来查询像HTTP这样的服务。这个脚本可以工作,但如果我有10个服务超时,脚本会因为每个服务超时1秒而总共耗时超过10秒。
我想要做的是让所有检查同时进行,这样可以减少完成所需的时间。
目前我遇到了段错误(segfault),但并不是每次都会出现。奇怪的是,在processCheck函数中检查主机时,我可以打印出所有主机。但在检查主机之后,hosts变量只打印出一两个主机。我觉得这可能是命名空间的问题,但不太确定怎么解决。
我在这里发布了整个代码,除了MySQL数据库的部分,但服务列表视图的结果看起来是这样的。
任何帮助都非常感谢。
6543L, 'moretesting.com', 'smtp')
(6543L, 'moretesting.com', 'ping')
(6543L, 'moretesting.com', 'http')
from commands import getstatusoutput
import MySQLdb
import threading
import Queue
import time
def checkHost(x, service):
command = {}
command['http'] = './plugins/check_http -t 1 -H '
command['smtp'] = './plugins/check_smtp -t 1 -H '
cmd = command[service]
cmd += x
retval = getstatusoutput(cmd)
if retval[0] == 0:
return 0
else:
return retval[1]
def fetchHosts():
hostList = []
cur.execute('SELECT veid, hostname, service from service_list')
for row in cur.fetchall():
hostList.append(row)
return hostList
def insertFailure(veid, hostname, service, error):
query = 'INSERT INTO failures (veid, hostname, service, error) '
query += "VALUES ('%s', '%s', '%s', '%s')" % (veid, hostname, service, error)
cur.execute(query)
cur.execute('COMMIT')
def processCheck(host):
#If I print the host tuple here I get all hosts/services
retval = checkHost(host[1], host[2])
#If I print the host tuple here, I get one host maybe two
if retval != 0:
try:
insertFailure(host[0], host[1], host[2], retval)
except:
pass
else:
try:
#if service is back up, remove old failure entry
query = "DELETE FROM failures WHERE veid='%s' AND service='%s' AND hostname='%s'" % (host[0], host[2], host[1])
cur.execute(query)
cur.execute('COMMIT')
except:
pass
return 0
class ThreadClass(threading.Thread):
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
processCheck(queue.get())
time.sleep(1)
def main():
for host in fetchHosts():
queue.put(host)
t = ThreadClass(queue)
t.setDaemon(True)
t.start()
if __name__ == '__main__':
conn = MySQLdb.connect('localhost', 'root', '', 'testing')
cur = conn.cursor()
queue = Queue.Queue()
main()
conn.close()
3 个回答
0
你应该先建立并填充你的队列。等队列完全建立好并且里面有东西后,再创建几个线程。每个线程会在一个循环中,不断地检查队列,并处理队列里的一个项目。
8
MySQL数据库的驱动程序不支持多线程安全。也就是说,你在多个线程中同时使用了同一个游标,这样会出问题。
你可以尝试在每个线程中创建一个新的连接,或者建立一个连接池,让线程们可以共享使用这些连接(比如把连接放在一个Queue
里,每个线程get
一个连接,使用完后再put
回去)。