многопоточный / многопроцессорный код Python - PullRequest
1 голос
/ 08 сентября 2010

В приведенном ниже коде я рассматриваю использование многопоточности или многопроцессорности для извлечения из URL. Я думаю, что бассейны были бы идеальными, Может кто-нибудь помочь предложить решение ..

Идея: объединить поток / процесс, собрать данные ... я предпочитаю процесс перед потоком, но не уверен.

import urllib

URL = "http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=sl1t1v&e=.csv"
symbols = ('GGP', 'JPM', 'AIG', 'AMZN','GGP', 'JPM', 'AIG', 'AMZN')
#symbols = ('GGP')

def fetch_quote(symbols):
    url = URL % '+'.join(symbols)
    fp = urllib.urlopen(url)
    try:
        data = fp.read()
    finally:
        fp.close()
    return data

def main():
    data_fp = fetch_quote(symbols)
#    print data_fp
if __name__ =='__main__':
    main()

Ответы [ 4 ]

1 голос
/ 08 сентября 2010

У вас есть процесс, который запрашивает несколько данных одновременно. Давайте попробуем получить эту информацию одну за другой .. Ваш код будет:

def fetch_quote(symbols):
    url = URL % '+'.join(symbols)
    fp = urllib.urlopen(url)
    try:
        data = fp.read()
    finally:
        fp.close()
    return data

def main():
    for symbol in symbols:
        data_fp = fetch_quote((symbol,))
        print data_fp

if __name__ == "__main__":
    main()

Итак, вызов main (), один за другим, для получения данных. Давайте мультипроцессировать его с пулом:

import urllib
from multiprocessing import Pool

URL = "http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=sl1t1v&e=.csv"
symbols = ('GGP', 'JPM', 'AIG', 'AMZN','GGP', 'JPM', 'AIG', 'AMZN')

def fetch_quote(symbols):
    url = URL % '+'.join(symbols)
    fp = urllib.urlopen(url)
    try:
        data = fp.read()
    finally:
        fp.close()
    return data

def main():
    for symbol in symbols:
        data_fp = fetch_quote((symbol,))
        print data_fp

if __name__ =='__main__':
    pool = Pool(processes=5)
    for symbol in symbols:
        result = pool.apply_async(fetch_quote, [(symbol,)])
        print result.get(timeout=1)

В следующем основном создан новый процесс для запроса URL каждого символа.

Примечание: на python, поскольку GIL присутствует, многопоточность должна рассматриваться как неправильное решение.

Для документации см .: Многопроцессорная обработка в Python

1 голос
/ 08 сентября 2010

Итак, вот очень простой пример. Он перебирает символы, передаваемые по одному за раз fetch_quote.

import urllib
import multiprocessing

URL = "http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=sl1t1v&e=.csv"
symbols = ('GGP', 'JPM', 'AIG', 'AMZN','GGP', 'JPM', 'AIG', 'AMZN')
#symbols = ('GGP')

def fetch_quote(symbol):
    url = URL % '+'.join(symbol)
    fp = urllib.urlopen(url)
    try:
        data = fp.read()
    finally:
        fp.close()
    return data


def main():

    PROCESSES = 4
    print 'Creating pool with %d processes\n' % PROCESSES
    pool = multiprocessing.Pool(PROCESSES)
    print 'pool = %s' % pool
    print

    results = [pool.apply_async(fetch_quote, sym) for sym in symbols]

    print 'Ordered results using pool.apply_async():'
    for r in results:
        print '\t', r.get()

    pool.close()
    pool.join()

if __name__ =='__main__':
    main()
0 голосов
/ 08 сентября 2010

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

мультипроцессы более эффективны в этом случае, но при этом возникают затраты времени и памяти на дополнительные процессы.Я недавно исследовал оба эти варианта в Python.Вот URL (с кодом) -

python -> модуль многопроцессорной обработки

0 голосов
/ 08 сентября 2010

На самом деле это можно сделать без них. Вы можете сделать это в одном потоке, используя асинхронные вызовы, например, twisted.web.client.getPage из Twisted Web .

...