Czy w bibliotece wieloprocesowej Python istnieje wariant pool.map, który obsługuje wiele argumentów?
text = "test"
def harvester(text, case):
X = case[0]
text+ str(X)
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=6)
case = RAW_DATASET
pool.map(harvester(text,case),case, 1)
pool.close()
pool.join()
python
multiprocessing
użytkownik642897
źródło
źródło
partial
anilambda
zrobić. Myślę, że ma to związek z dziwnym sposobem przekazywania funkcji do podprocesów (viapickle
).pool.map(harvester(text,case),case, 1)
:pool.apply_async(harvester(text,case),case, 1)
return
doharvester()
przekształciło odpowiedź @senderie w niedokładną. To nie pomaga przyszłym czytelnikom.Odpowiedzi:
Odpowiedź na to pytanie zależy od wersji i sytuacji. Najbardziej ogólną odpowiedź na ostatnie wersje Pythona (od 3.3) po raz pierwszy opisano poniżej JF Sebastian . 1 Wykorzystuje
Pool.starmap
metodę, która akceptuje ciąg krotek argumentów. Następnie automatycznie rozpakowuje argumenty z każdej krotki i przekazuje je do podanej funkcji:We wcześniejszych wersjach Pythona musisz napisać funkcję pomocnika, aby jawnie rozpakować argumenty. Jeśli chcesz użyć
with
, musisz także napisać opakowanie, aby zmienićPool
się w menedżera kontekstu. (Dzięki mion za wskazanie tego.)W prostszych przypadkach, ze stałym drugim argumentem, możesz także użyć
partial
, ale tylko w Python 2.7+.1. Wiele z tego zostało zainspirowanych jego odpowiedzią, która prawdopodobnie powinna była zostać zaakceptowana. Ale ponieważ ten utknął na górze, najlepszym rozwiązaniem dla przyszłych czytelników wydawało się jego ulepszenie.
źródło
=RAW_DATASET
wartości domyślnejcase
. W przeciwnym razie wprowadzi wpool.map
błąd wiele argumentów.text
zmienną w twoim przykładzie? DlaczegoRAW_DATASET
pozornie minął dwa razy. Myślę, że możesz mieć literówkę?with .. as ..
daje miAttributeError: __exit__
, ale działa dobrze, jeśli po prostu zadzwonię,pool = Pool();
a następnie zamknę ręczniepool.close()
(python2.7)Pool
obiekty nie stają się menedżerami kontekstu, dopóki Python 3.3. Dodałem prostą funkcję opakowania, która zwracaPool
menedżera kontekstu.Python 3.3 obejmuje
pool.starmap()
metodę :W przypadku starszych wersji:
Wynik
Zauważ, jak
itertools.izip()
iitertools.repeat()
są tutaj używane.Z powodu błędu wspomnianego przez @unutbu nie można używać
functools.partial()
ani podobnych możliwości w Pythonie 2.6, więc prosta funkcja otokifunc_star()
powinna być wyraźnie zdefiniowana. Zobacz także obejście sugerowane przezuptimebox
.źródło
func_star
tak:def func_star((a, b))
. Oczywiście działa to tylko dla określonej liczby argumentów, ale jeśli jest to jedyny przypadek, jaki ma, jest bardziej czytelny.f((a,b))
składnia jest przestarzała i usunięta w py3k. I tutaj nie jest to konieczne.func = lambda x: func(*x)
zamiast definiować funkcję otokifunc_star()
powyżej)starstarmap
.Myślę, że poniżej będzie lepiej
wynik
źródło
args
bezpośrednioadd
, działa na dowolną liczbę argumentów:def add(args): (x,y) = args
lambda
funkcji zamiast definiowaćmulti_run_wrapper(..)
lambda
nie działa, ponieważpool.map(..)
próbuje marynować daną funkcjęadd
na liście?Używanie Python 3.3+ z
pool.starmap():
Wynik:
Możesz także spakować () więcej argumentów, jeśli chcesz:
zip(a,b,c,d,e)
W przypadku, gdy chcemy mieć wartość stałą przekazany jako argument trzeba użyć
import itertools
, a następniezip(itertools.repeat(constant), a)
na przykład.źródło
Po zapoznaniu się z itertools w odpowiedzi JF Sebastiana postanowiłem pójść o krok dalej i napisać
parmap
pakiet, który dba o równoległość, oferowaniemap
istarmap
funkcje w python-2.7 i python-3.2 (i później również), które mogą przyjmować dowolną liczbę argumentów pozycyjnych .Instalacja
Jak zrównoleglić:
Przesłałem Parmap do PyPI i do repozytorium github .
Na przykład na pytanie można odpowiedzieć w następujący sposób:
źródło
# „Jak wziąć wiele argumentów”.
źródło
Istnieje widelec
multiprocessing
zwany pathos ( uwaga: użyj wersji na github ), który nie potrzebujestarmap
- funkcje map odzwierciedlają API dla mapy pythona, więc mapa może przyjmować wiele argumentów. Za pomocąpathos
można ogólnie wykonywać wiele procesów w interprecie, zamiast utknąć w__main__
bloku. Pathos ma się ukazać po niewielkiej aktualizacji - głównie konwersji na Python 3.x.pathos
ma kilka sposobów uzyskania dokładnego zachowaniastarmap
.źródło
Możesz użyć następujących dwóch funkcji, aby uniknąć pisania opakowania dla każdej nowej funkcji:
Użyj funkcji
function
z listy argumentówarg_0
,arg_1
aarg_2
w następujący sposób:źródło
Lepsze rozwiązanie dla python2:
2 3 4
1 2 3
0 1 2
na zewnątrz[]:
[3, 5, 7]
źródło
Inną prostą alternatywą jest zawinięcie parametrów funkcji w krotkę, a następnie zawinięcie parametrów, które należy przekazać również w krotkach. Być może nie jest to idealne rozwiązanie w przypadku dużych danych. Wierzę, że zrobiłby kopie dla każdej krotki.
Daje wynik w jakiejś losowej kolejności:
źródło
Lepszym sposobem jest użycie dekoratora zamiast ręcznego pisania funkcji owijania . Zwłaszcza, gdy masz wiele funkcji do mapowania, dekorator oszczędza Twój czas, unikając pisania opakowań dla każdej funkcji. Zazwyczaj dekorowanej funkcji nie można odebrać, jednak możemy użyć jej
functools
do obejścia. Więcej dyskusji można znaleźć tutaj .Oto przykład
Następnie możesz zmapować go za pomocą spakowanych argumentów
Oczywiście zawsze możesz używać
Pool.starmap
w Pythonie 3 (> = 3.3), jak wspomniano w innych odpowiedziach.źródło
itertools.product
zamiastzip
.Innym sposobem jest przekazanie listy list do procedury z jednym argumentem:
Można zbudować listę list argumentów za pomocą ulubionej metody.
źródło
Oto inny sposób, aby to zrobić, że IMHO jest prostsze i bardziej eleganckie niż jakakolwiek inna podana odpowiedź.
Ten program ma funkcję, która pobiera dwa parametry, drukuje je, a także drukuje sumę:
wyjście to:
Zobacz dokumentację Pythona, aby uzyskać więcej informacji:
https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.pool
W szczególności sprawdź
starmap
funkcję.Używam Python 3.6, nie jestem pewien, czy to zadziała ze starszymi wersjami Python
Dlaczego nie ma tak prostego przykładu w dokumentacji, nie jestem pewien.
źródło
W Pythonie 3.4.4 można użyć multiprocessing.get_context (), aby uzyskać obiekt kontekstowy do korzystania z wielu metod uruchamiania:
Lub po prostu zastępujesz
przez:
źródło
Istnieje wiele odpowiedzi tutaj, ale wydaje się, że żadna nie zapewnia kodu zgodnego z Python 2/3, który będzie działał w dowolnej wersji. Jeśli chcesz, aby Twój kod działał , zadziała to dla dowolnej wersji Python:
Następnie możesz używać wieloprocesowego przetwarzania w zwykły sposób w Pythonie 3, jak chcesz. Na przykład:
będzie działał w Python 2 lub Python 3.
źródło
W oficjalnej dokumentacji stwierdzono, że obsługuje tylko jeden iterowalny argument. W takich przypadkach lubię stosować Apply_async. W twoim przypadku zrobiłbym:
źródło
źródło
To jest przykład procedury, której używam do przekazywania wielu argumentów do funkcji jednego argumentu używanej w rozwidleniu pool.imap :
źródło
w przypadku python2 możesz użyć tej sztuczki
źródło