Python线程测试不工作

Python线程测试不工作,python,multithreading,Python,Multithreading,编辑 我通过分叉进程而不是使用线程解决了这个问题。从评论中的评论和链接来看,我认为线程化不是正确的做法 谢谢大家的帮助 完成编辑 我以前在线程方面做得不多。我已经创建了一些简单的示例Hello World脚本,但实际上没有任何效果 为了帮助我掌握它,我使用Nagios的二进制文件编写了一个简单的脚本来查询HTTP等服务。此脚本可以工作,但超时时间为1秒。如果我有10个服务超时,则脚本将花费超过10秒的时间 我要做的是并行运行所有检查。这将减少完成所需的时间 我现在有很多缺点,但不是一直都有。奇怪

编辑

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

谢谢大家的帮助

完成编辑

我以前在线程方面做得不多。我已经创建了一些简单的示例Hello World脚本,但实际上没有任何效果

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

我要做的是并行运行所有检查。这将减少完成所需的时间

我现在有很多缺点,但不是一直都有。奇怪的是,当我在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()

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


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

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


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

您应该先构建和填充队列。构建和填充整个队列后,您应该构建多个线程,每个线程在循环中轮询队列并处理队列上的项目。

您应该首先构建和填充队列。当构建和填充整个队列时,您应该构建多个线程,每个线程在一个循环中轮询队列并处理队列上的一个项目。

您意识到Python并不像您在多核处理器上期望的那样执行真正的多线程:


不要期望这10件事每件都花1秒钟。此外,即使在真正的多线程中,也有一些线程相关的开销。我想补充一点,这并不是对Python的污蔑。

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


不要期望这10件事每件都花1秒钟。此外,即使在真正的多线程中,也有一些线程相关的开销。我想补充一点,这并不是对Python的污蔑。

您使用的是什么操作系统/平台?请记住,由于全局解释器锁,Python实际上无法进行并发操作。有关详细信息,请参阅。@qid-仅适用于Python字节码,不适用于外部C代码或任何类型的阻止代码,例如DB Access。此外,您应该使用参数化查询,而不是将文本转换为字符串文本。没有借口,用Python/DB-API真的很容易。@Seth。请用问题的形式回答这个问题。只是个问题。所有的事实。然后——如果你愿意——分别回答你自己的问题。不要对这个问题闭口不谈。只需创建一个问题和一个答案。您使用的是什么操作系统/平台?请记住,由于全局解释器锁,Python实际上无法进行并发操作。有关详细信息,请参阅。@qid-仅适用于Python字节码,不适用于外部C代码或任何类型的阻止代码,例如DB Access。此外,您应该使用参数化查询,而不是将文本转换为字符串文本。没有借口,用Python/DB-API真的很容易。@Seth。请用问题的形式回答这个问题。只是个问题。所有的事实。然后——如果你愿意——分别回答你自己的问题。不要对这个问题闭口不谈。创建一个问题和一个答案。谢谢。我已经更改了代码,每次启动新连接时都会出现相同的问题。命令模块是否可能不是线程安全的?这似乎就是问题所在。如果命令模块不是线程安全的,我会感到惊讶,但无论如何,它已被弃用-首选子流程模块。谢谢。我已经更改了代码,每次启动新连接时都会出现相同的问题。命令模块是否可能不是线程安全的?这似乎就是问题所在。如果命令模块不是线程安全的,我会感到惊讶,但在任何情况下,它都不推荐使用-首选子流程模块。感谢提供的信息。多愁善感
你认为为每一张支票创建一个叉子会有效吗?据我所知,每个分叉都应该认为是独立的。因为它在与MySQL对话,所以我不需要来回传递任何变量。@wheaties-仅用于Python字节码。访问数据库并运行子进程可以释放GIL,Python代码本身在这里并不慢,因此他应该得到线性加速,例如总共1秒。感谢您提供的信息。你认为为每一张支票创建一个分叉行行吗?据我所知,每个分叉都应该认为是独立的。因为它在与MySQL对话,所以我不需要来回传递任何变量。@wheaties-仅用于Python字节码。访问数据库并运行子进程可以释放GIL,而Python代码本身在这里并不慢,因此他应该得到线性加速,例如总共1秒。