Python: Как я могу исправить этот код, чтобы он работал в Windows? - PullRequest
0 голосов
/ 12 ноября 2011
import lxml.html
import mechanize, cookielib
import multiprocessing

browser = None

def download(i):
    link = 'www.google.com'
    response = browser.open(link)
    tree = lxml.html.parse(response)
    print tree
    return 0

if __name__ == '__main__':    
    browser = mechanize.Browser()
    cookie_jar = cookielib.LWPCookieJar()
    browser.set_cookiejar(cookie_jar)
    browser.set_handle_equiv(True)
    browser.set_handle_gzip(True)
    browser.set_handle_redirect(True)
    browser.set_handle_referer(False) #inicialmente estava on mas deve ser melhor off
    browser.set_handle_robots(False)
    browser.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
    browser.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:2.0.1) Gecko/20100101 Ubuntu/11.04 maverick Firefox/4.0.1')]

    pool = multiprocessing.Pool(None)
    tasks = range(8)
    r = pool.map_async(download, tasks)
    r.wait() # Wait on the results

Если я удаляю многопроцессорную часть, она работает. Если я не вызываю браузер внутри функции загрузки, это также работает. Однако кажется, что многопроцессорная обработка + механизация просто не работают.

Как я могу это исправить? Это не происходит под Linux.

Ответы [ 2 ]

0 голосов
/ 12 ноября 2011

Только основной процесс выполняет стробированный блок if __name__ == '__main__'.Поскольку в Windows отсутствует системный вызов fork, каждому процессу, созданному в пуле, необходим собственный браузер.Вы можете сделать это с помощью функции инициализатора.Для справки см. Опции initializer и initargs многопроцессорной обработки . Бассейн .

import lxml.html
import mechanize, cookielib
import multiprocessing as mp

def download(i):
    link = 'http://www.google.com'
    response = browser.open(link)
    tree = lxml.html.parse(response)
    print tree
    return 0

def init(count):
    global browser
    browser = mechanize.Browser()
    cookie_jar = cookielib.LWPCookieJar()
    browser.set_cookiejar(cookie_jar)
    browser.set_handle_equiv(True)
    browser.set_handle_gzip(True)  #warning
    browser.set_handle_redirect(True)
    browser.set_handle_referer(False)
    browser.set_handle_robots(False)
    browser.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), 
                               max_time=1)
    browser.addheaders = [('User-agent', 
        'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:2.0.1) '
        'Gecko/20100101 Ubuntu/11.04 maverick Firefox/4.0.1')]

    count.value -= 1

if __name__ == '__main__':
    import time
    count = mp.Value('I', mp.cpu_count())
    pool = mp.Pool(count.value, initializer=init, initargs=(count,))
    #wait until all processes are initialized
    while count.value > 0:
        time.sleep(0.1)

    tasks = range(8)
    r = pool.map_async(download, tasks)
    r.wait()
0 голосов
/ 12 ноября 2011

Я бы попробовал:

  • удалить browser = None или
  • переместите код в __name__=="__main__" в функцию main() и добавьте global browser перед browser=mechanize.Browser() или
  • код перемещения, который инициализирует browser, в initializer

Если ваши задачи связаны с вводом / выводом, вам не обязательно multiprocessing делать параллельные запросы. Например, вместо этого вы можете использовать concurrent.futures.ThreadPoolExecutor, gevent, Twisted.

Related: Проблема с многопоточным приложением Python и соединениями с сокетом

...