пример urllib3 и многопоточность в python - PullRequest
2 голосов
/ 17 сентября 2010

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

Создайте 1 соединение для каждого потока (я не понимаю, почему) и зависайте навсегда. Любой совет, совет или простой пример urllib3 и threading

import threadpool
from urllib3 import connection_from_url

HTTP_POOL = connection_from_url(url, timeout=10.0, maxsize=10, block=True)

def fetch(url, fiedls):
  kwargs={'retries':6}
  return HTTP_POOL.get_url(url, fields, **kwargs)

pool = threadpool.ThreadPool(5)
requests = threadpool.makeRequests(fetch, iterable)
[pool.putRequest(req) for req in requests]

@ Сценарий Леннарта получил эту ошибку:

http://en.wikipedia.org/wiki/2010-11_Premier_LeagueTraceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/threadpool.py", line 156, in run
 http://en.wikipedia.org/wiki/List_of_MythBusters_episodeshttp://en.wikipedia.org/wiki/List_of_Top_Gear_episodes http://en.wikipedia.org/wiki/List_of_Unicode_characters    result = request.callable(*request.args, **request.kwds)
  File "crawler.py", line 9, in fetch
    print url, conn.get_url(url)
AttributeError: 'HTTPConnectionPool' object has no attribute 'get_url'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/threadpool.py", line 156, in run
    result = request.callable(*request.args, **request.kwds)
  File "crawler.py", line 9, in fetch
    print url, conn.get_url(url)
AttributeError: 'HTTPConnectionPool' object has no attribute 'get_url'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/threadpool.py", line 156, in run
    result = request.callable(*request.args, **request.kwds)
  File "crawler.py", line 9, in fetch
    print url, conn.get_url(url)
AttributeError: 'HTTPConnectionPool' object has no attribute 'get_url'
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/threadpool.py", line 156, in run
    result = request.callable(*request.args, **request.kwds)
  File "crawler.py", line 9, in fetch
    print url, conn.get_url(url)
AttributeError: 'HTTPConnectionPool' object has no attribute 'get_url'

После добавления import threadpool; import urllib3 и tpool = threadpool.ThreadPool(4) @ user318904 код получил эту ошибку:

Traceback (most recent call last):
  File "crawler.py", line 21, in <module>
    tpool.map_async(fetch, urls)
AttributeError: ThreadPool instance has no attribute 'map_async'

Ответы [ 4 ]

1 голос
/ 04 сентября 2018

Вот мое мнение, более современное решение с использованием Python3 и concurrent.futures.ThreadPoolExecutor.

import urllib3
from concurrent.futures import ThreadPoolExecutor

urls = ['http://en.wikipedia.org/wiki/2010-11_Premier_League',
        'http://en.wikipedia.org/wiki/List_of_MythBusters_episodes',
        'http://en.wikipedia.org/wiki/List_of_Top_Gear_episodes',
        'http://en.wikipedia.org/wiki/List_of_Unicode_characters',
        ]

def download(url, cmanager):
    response = cmanager.request('GET', url)
    if response and response.status == 200:
        print("+++++++++ url: " + url)
        print(response.data[:1024])

connection_mgr = urllib3.PoolManager(maxsize=5)
thread_pool = ThreadPoolExecutor(5)
for url in urls:
    thread_pool.submit(download, url, connection_mgr)

Некоторые замечания

  • Мой код основан на похожем примере из Python Cookbook Бизли и Джонса.
  • Мне особенно нравится тот факт, что вам нужен только стандартный модуль, кроме urllib3.
  • Настройка чрезвычайно проста, и если вы собираетесь использовать только побочные эффекты в download (например, печать, сохранение в файл и т. Д.), Не требуется дополнительных усилий для объединения потоков.
  • Если вы хотите что-то другое, ThreadPoolExecutor.submit фактически возвращает то, что вернуло бы download, обернутый в Future.
  • Мне показалось полезным выровнять количество потоков в пуле потоков с количеством HTTPConnection в пуле соединений (через maxsize). В противном случае вы можете столкнуться с (безвредными) предупреждениями, когда все потоки пытаются получить доступ к одному и тому же серверу (как в примере).
1 голос
/ 27 июля 2011

Программирование потоков сложно, поэтому я написал workerpool , чтобы сделать именно то, что вы делаете, проще.

Более конкретно, посмотрите пример Mass Downloader .

Чтобы сделать то же самое с urllib3, он выглядит примерно так:

import urllib3
import workerpool

pool = urllib3.connection_from_url("foo", maxsize=3)

def download(url):
    r = pool.get_url(url)
    # TODO: Do something with r.data
    print "Downloaded %s" % url

# Initialize a pool, 5 threads in this case
pool = workerpool.WorkerPool(size=5)

# The ``download`` method will be called with a line from the second 
# parameter for each job.
pool.map(download, open("urls.txt").readlines())

# Send shutdown jobs to all threads, and wait until all the jobs have been completed
pool.shutdown()
pool.wait()

Для более сложного кода, взгляните на workerpool.EquippedWorker (и тесты здесь например использование).Вы можете сделать пул toolbox, который вы передаете.

1 голос
/ 13 января 2011

Очевидно, что это создаст одно соединение на поток, как иначе каждый поток сможет получить страницу? И вы пытаетесь использовать одно и то же соединение, созданное из одного URL-адреса, для всех URL-адресов. Это вряд ли может быть то, что вы хотели.

Этот код работал просто отлично:

import threadpool
from urllib3 import connection_from_url

def fetch(url):
  kwargs={'retries':6}
  conn = connection_from_url(url, timeout=10.0, maxsize=10, block=True)
  print url, conn.get_url(url)
  print "Done!"

pool = threadpool.ThreadPool(4)
urls = ['http://en.wikipedia.org/wiki/2010-11_Premier_League',
        'http://en.wikipedia.org/wiki/List_of_MythBusters_episodes',
        'http://en.wikipedia.org/wiki/List_of_Top_Gear_episodes',
        'http://en.wikipedia.org/wiki/List_of_Unicode_characters',
        ]
requests = threadpool.makeRequests(fetch, urls)

[pool.putRequest(req) for req in requests]
pool.wait()
0 голосов
/ 04 апреля 2011

Я использую что-то вроде этого:

#excluding setup for threadpool etc

upool = urllib3.HTTPConnectionPool('en.wikipedia.org', block=True)

urls = ['/wiki/2010-11_Premier_League',
        '/wiki/List_of_MythBusters_episodes',
        '/wiki/List_of_Top_Gear_episodes',
        '/wiki/List_of_Unicode_characters',
        ]

def fetch(path):
    # add error checking
    return pool.get_url(path).data

tpool = ThreadPool()

tpool.map_async(fetch, urls)

# either wait on the result object or give map_async a callback function for the results
...