Python Feedparser и многопоточность

У меня есть список (почти 500) URL-адресов RSS/ATOM-каналов для анализа и извлечения ссылок.

Я использую библиотеку python feedparser для анализа URL-адреса. Чтобы параллельно анализировать список URL-адресов, я подумал об использовании библиотеки потоков в python.

Мой код выглядит примерно так

import threading
import feedparser

class PullFeeds:
    def _init__(self):
        self.data = open('urls.txt', 'r')

    def pullfeed(self):
        threads = []
        for url in self.data:
             t = RssParser(url)
             threads.append(t)
        for thread in threads:
             thread.start()
        for thread in threads:
             thread.join()

class RssParser(threading.Thread):
     def __init__(self, url):
         threading.Thread.__init__(self)
         self.url = url

     def run(self):
         print "Starting: ", self.name
         rss_data = feedparser.parse(self.url)
         for entry in rss_data.get('entries'):
             print entry.get('link')
         print "Exiting: ", self.name


pf = PullFeeds()
pf.pullfeed()

Проблема в том, что при запуске этого скрипта из Feedparser возвращается пустой список. Но без потоковой обработки feedparser распечатывает список ссылок, проанализированных из предоставленного URL-адреса.

Как я могу это исправить?


person Prashere    schedule 18.04.2014    source источник


Ответы (2)


Чтобы увидеть, связана ли проблема с многопоточностью, вы можете вместо этого попробовать использовать несколько процессов:

#!/usr/bin/env python
####from multiprocessing.dummy import Pool # use threads
from multiprocessing import Pool # use processes
from multiprocessing import freeze_support
import feedparser

def fetch_rss(url):
    try:
        data = feedparser.parse(url)
    except Exception as e:
        return url, None, str(e)
    else:
        e = data.get('bozo_exception')
        return url, data['entries'], str(e) if e else None

if __name__=="__main__":
    freeze_support()
    with open('urls.txt') as file:
        urls = (line.strip() for line in file if line.strip())
        pool = Pool(20) # no more than 20 concurrent downloads
        for url, items, error in pool.imap_unordered(fetch_rss, urls):
            if error is None:
                print(url, len(items))
            else:
                print(url, error)
person jfs    schedule 18.04.2014
comment
Я постараюсь вернуться к вам в ближайшее время. Спасибо за помощь. - person Prashere; 19.04.2014

Проблема была с Vagrant. Я запускал скрипт внутри одной из моих бродячих машин. Тот же скрипт отлично работает из бродячего ящика.

Об этом нужно было сообщить. Я еще не уверен, куда сообщить об этой ошибке, будь то проблема с потоками Vagrant или Python или библиотекой Feedparser.

person Prashere    schedule 20.04.2014