#python #multithreading #data-mining
#python #многопоточность #интеллектуальный анализ данных
Вопрос:
Я пишу data miner на python с urllib2 и BeautifulSoup для анализа некоторых веб-сайтов, и, пытаясь разделить его процессы на несколько потоков, я получаю следующий результат:
Успешно очищенный идентификатор 301
Успешно очищенный идентификатор 301
Пустой результат с идентификатором 301
«Успешно» означает, что я получил нужные мне данные. «Пусто» означает, что на странице нет того, что мне нужно. «ID» — это целое число, прикрепленное к URL-адресу, например site.com/blog/post /.
Во-первых, каждый поток должен анализировать разные URL-адреса, а не одни и те же URL-адреса много раз. Во-вторых, я не должен получать разные результаты для одного и того же URL-адреса.
Я распределяю процессы следующим образом: я создаю несколько потоков, передаю каждому из них общие части списка URL-адресов для анализа и отправляю их в путь. Вот код:
def constructURLs(settings,idList):
assert type(settings) is dict
url = settings['url']
return [url.replace('<id>',str(ID)) for ID in idList]
def miner(urls,results):
for url in urls:
data = spider.parse(url)
appendData(data,results)
def mine(settings,results):
(...)
urls = constructURLs(settings,idList)
threads = 3 # number of threads
urlList = [urls[i::threads] for i in xrange(threads)]
for urls in urlList:
t = threading.Thread(target=miner,args=(urls,results))
t.start()
Итак, почему мои потоки анализируют одни и те же результаты много раз, когда все они должны иметь уникальные списки? Почему они возвращают разные результаты, даже с одним и тем же идентификатором? Если вы хотите увидеть больше кода, просто спросите, и я с радостью предоставлю. Спасибо за любую информацию, которую вы можете предоставить!
Комментарии:
1. Является ли ваша функция appendData() потокобезопасной? Если он вызывается повторно из нескольких потоков, все используемые им общие переменные могут быть перезаписаны.
2. Это объяснило бы многие идентификаторы, которые отсутствуют в файле результатов, но инструкции печати об успешном выполнении очистки выполняются перед записью в результаты.
3. На самом деле, проблема потокобезопасности может быть причиной. Ошибка происходит внутри parse(), я это знаю. Функция использует локальную переменную модуля, которую изменяют все экземпляры функции. Вероятно, именно здесь возникает ошибка. Спасибо за ваше понимание!