Ответ 1
Urllib использует cpython глубоко в модуле сокета, поэтому потоки которые создаются, просто складываются и ничего не делают, потому что python GIL предотвращает выполнение двух команд cpython в неуверенном потоков в то же время.
Неправильно. Хотя это распространенное заблуждение. CPython может и выпускает GIL для операций ввода-вывода (посмотрите на Py_BEGIN_ALLOW_THREADS
в socketmodule.c
). Хотя один поток ожидает завершения ввода-вывода, другие потоки могут выполнять некоторую работу. Если вызовы urllib
являются узким местом в вашем script, тогда потоки могут быть одним из приемлемых решений.
Я запускаю Windows XP с Python 2.5, поэтому я не могу использовать многопроцессорный модуль.
Вы можете установить Python 2.6 или новее или использовать Python 2.5; вы можете установить multiprocessing отдельно.
Я создал собственный пользовательский модуль времени, подобный модулю, и выше занимает около 0,5-2 секунд, что ужасно для моей программы.
Производительность urllib2.urlopen('http://example.com...).read()
в основном зависит от внешних факторов, таких как DNS, латентность/пропускная способность сети, производительность самого сервера example.com.
Здесь приведен пример script, который использует как threading
, так и urllib2
:
import urllib2
from Queue import Queue
from threading import Thread
def check(queue):
"""Check /n url."""
opener = urllib2.build_opener() # if you use install_opener in other threads
for n in iter(queue.get, None):
try:
data = opener.open('http://localhost:8888/%d' % (n,)).read()
except IOError, e:
print("error /%d reason %s" % (n, e))
else:
"check data here"
def main():
nurls, nthreads = 10000, 10
# spawn threads
queue = Queue()
threads = [Thread(target=check, args=(queue,)) for _ in xrange(nthreads)]
for t in threads:
t.daemon = True # die if program exits
t.start()
# provide some work
for n in xrange(nurls): queue.put_nowait(n)
# signal the end
for _ in threads: queue.put(None)
# wait for completion
for t in threads: t.join()
if __name__=="__main__":
main()
Чтобы преобразовать его в многопроцессорную систему script, просто используйте разные импорты, и ваша программа будет использовать несколько процессов:
from multiprocessing import Queue
from multiprocessing import Process as Thread
# the rest of the script is the same