Тест потока Python не работает - PullRequest
1 голос
/ 10 ноября 2009

EDIT

Я решил проблему, развязав процесс вместо использования потоков. Судя по комментариям и ссылкам в комментариях, я не думаю, что многопоточность - это правильный шаг.

Спасибо всем за помощь.

Закончено редактирование

Раньше я ничего не делал с потоками. Я создал несколько простых примеров сценариев «Hello World», но ничего такого, что действительно не помогало.

Чтобы помочь мне понять это, я написал простой скрипт, использующий двоичные файлы из Nagios для запросов к таким службам, как HTTP. Этот сценарий работает, хотя со временем ожидания 1 секунда, если у меня есть 10 служб, время выполнения сценария будет превышать 10 секунд.

Что я хочу сделать, так это запустить все проверки параллельно друг другу. Это должно сократить время, необходимое для завершения.

В настоящее время я получаю segfaults, но не все время. Странно, что в момент, когда я проверяю хост в функции 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 ]

8 голосов
/ 10 ноября 2009

Драйвер MySQL DB не является поточно-ориентированным. Вы используете один и тот же курсор одновременно из всех потоков.

Попробуйте создать новое соединение в каждом потоке или создать пул соединений, которые могут использовать потоки (например, сохранить их в Queue, в каждом потоке get sa, и put s, когда оно упаковывается, сделано).

0 голосов
/ 10 ноября 2009

Вы понимаете, что Python не выполняет настоящую многопоточность, как вы ожидаете от многоядерного процессора:

Смотрите здесь и здесь

Не ожидайте, что эти 10 вещей займут 1 секунду каждая. Кроме того, даже в настоящей многопоточности есть небольшие издержки, связанные с потоками. Я хотел бы добавить, что это не пятно против Питона.

0 голосов
/ 10 ноября 2009

Вы должны сначала создать и заполнить свою очередь. Когда вся очередь создается и заполняется, вы должны создать несколько потоков, которые затем, каждый в цикле, опрашивают очередь и обрабатывают элемент в очереди.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...