2009-06-11 3 views
2

Я пишу приложение графического интерфейса в Pyglet, которое должно отображать десятки-сотни эскизов из Интернета. Прямо сейчас, я использую urllib.urlretrieve, чтобы захватить их, но это блокируется каждый раз, пока они не закончены, и только захватывает по одному.Как сделать неблокирующий URL-выбор в Python

Я бы предпочел загрузить их параллельно и иметь каждый дисплей сразу после его завершения, без блокировки GUI в любой точке. Каков наилучший способ сделать это?

Я не знаю много о потоках, но похоже, что модуль threading может помочь? Или, может быть, есть какой-то простой способ, который я забыл.

ответ

3

Вы, вероятно, выиграют от threading или multiprocessing модулей. Вы на самом деле не нужно создавать все эти Thread -На классы самостоятельно, есть более простой способ, использующий Pool.map:

from multiprocessing import Pool 

def fetch_url(url): 
    # Fetch the URL contents and save it anywhere you need and 
    # return something meaningful (like filename or error code), 
    # if you wish. 
    ... 

pool = Pool(processes=4) 
result = pool.map(f, image_url_list) 
+0

Есть ли эквивалент пула для потоков? Похоже, что он запускает отдельные процессы, которые могут быть тяжелее, чем мне нужно. – Kiv

+0

Кажется, что нет встроенного, но я нашел это: http://www.chrisarndt.de/projects/threadpool/, и он кажется очень похожим. – drdaeman

+0

Спасибо, threadpool работает отлично. – Kiv

2

Как вы подозревали, это идеальная ситуация для нарезки. Here - это краткое руководство, которое я нашел очень полезным, когда делал свой собственный первый бит потоковой передачи в python.

2

Как вы правильно указали, вы можете создать несколько потоков, каждый из которых отвечает за выполнение операций urlretrieve. Это позволяет непрерывной работе основного потока.

Вот учебник по многопоточности в Python: http://heather.cs.ucdavis.edu/~matloff/Python/PyThreads.pdf

+0

Спасибо за учебник, это было полезно. – Kiv

2

Вот пример того, как использовать threading.Thread. Просто замените имя класса своей собственной и функцией запуска на свой собственный. Обратите внимание, что многопоточность отлично подходит для приложений с ограниченным доступом, таких как ваши, и может действительно ускорить их. Использование pythong threading строго для вычисления в стандартном python не помогает, потому что только один поток может вычислять за раз.

import threading, time 
class Ping(threading.Thread): 
    def __init__(self, multiple): 
     threading.Thread.__init__(self) 
     self.multiple = multiple 
    def run(self): 
     #sleeps 3 seconds then prints 'pong' x times 
     time.sleep(3) 
     printString = 'pong' * self.multiple 

pingInstance = Ping(3) 
pingInstance.start() #your run function will be called with the start function 
print "pingInstance is alive? : %d" % pingInstance.isAlive() #will return True, or 1 
print "Number of threads alive: %d" % threading.activeCount() 
#main thread + class instance 
time.sleep(3.5) 
print "Number of threads alive: %d" % threading.activeCount() 
print "pingInstance is alive?: %d" % pingInstance.isAlive() 
#isAlive returns false when your thread reaches the end of it's run function. 
#only main thread now 
0

Вы либо должны использовать потоки, или асинхронный сетевой библиотеки, такие как Twisted. Я подозреваю, что использование потоков может быть проще в вашем конкретном случае использования.

1

У вас есть такой выбор:

  • Темы: простой, но не очень хорошо масштабируется
  • Twisted: средняя сложность, хорошо масштабируется, но акции CPU из-за GIL и быть однопоточным.
  • Многопроцессорные: самые сложные. Хорошо масштабируется, если вы знаете, как написать собственный цикл событий.

Я рекомендую использовать только потоки, если вам не нужен промышленный навес.

 Смежные вопросы

  • Нет связанных вопросов^_^