Python线程测试不起作用

时间:2009-11-09 21:46:09

标签: python multithreading

修改

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

感谢大家的帮助。

完成编辑

我之前没有做太多线程。我创建了一些简单的示例“Hello World”脚本,但实际上没有任何工作。

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

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

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

我在这里发布了整个代码没有MySQL数据库,但是他的service_list视图的结果看起来像。

非常感谢任何帮助。

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 DB驱动程序不是线程安全的。您在所有线程中同时使用相同的游标。

尝试在每个线程中创建一个新连接,或创建一个线程可以使用的连接池(例如,将它们保存在Queue,每个线程get sa连接,以及{{1}它完成时就打包了。)

答案 1 :(得分:0)

您应该首先构建并填充队列。构建并填充整个队列时,您应该构造一些线程,然后在循环中轮询队列并处理队列中的项目。

答案 2 :(得分:0)

你意识到Python并没有像你期望的那样在多核处理器上实现真正的多线程:

See Here And Here

不要指望这10件事每件花1秒钟。此外,即使在真正的多线程中,线程也会产生一些开销。我想补充一点,这不是对Python的诽谤。