Skip to main content
 首页 » 编程设计

Python线程测试不起作用

2025年05月04日1152php

编辑

我通过 fork 进程而不是使用线程解决了这个问题。从评论中的评论和链接来看,我认为线程在这里不是正确的举动。

感谢大家的帮助。

完成编辑

我之前对线程的了解不多。我创建了一些简单的示例“Hello World”脚本,但实际上没有任何效果。

为了帮助我掌握它,我使用 Nagios 的二进制文件编写了一个简单的脚本来查询 HTTP 等服务。如果我有 10 个服务超时,这个脚本虽然超时为 1 秒,但该脚本将花费 10 秒以上的时间。

我想做的是并行运行所有检查。这应该会减少完成所需的时间。

我目前遇到了段错误,但并非总是如此。奇怪的是,当我在 processCheck 函数中检查主机时,我可以打印出所有主机。不过,在检查主机之后,hosts 变量仅打印集合中的一两个主机。我感觉这是一个命名空间问题,但我不确定如何解决。

我已经在此处发布了没有 MySQL 数据库的整个代码,但 service_list View 的结果看起来像这样。

非常感谢任何帮助。

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() 

请您参考如下方法:

MySQL 数据库驱动程序不是线程安全的。您在所有线程中同时使用同一个游标。

尝试在每个线程中创建一个新连接,或者创建一个线程可以使用的连接池(例如,将它们保存在一个队列中,每个线程获取一个连接,并在完成后将打包)。