Kako uporabljati niti v Pythonu?
Poskušam razumeti nitkanje v Pythonu. Ogledal sem si dokumentacijo in primere, vendar so, odkrito povedano, mnogi primeri prezahtevni in jih težko razumem.
Kako jasno prikažete razdelitev opravil za večnitnost?
1204
3
Tukaj je preprost primer: preizkusiti morate nekaj alternativnih naslovov URL in vrniti vsebino prvega, ki se odzove.
To je primer, v katerem se nitkanje uporablja kot preprosta optimizacija: Vsaka podnita čaka, da se URL razreši in odgovori, da bi njegovo vsebino prenesla v čakalno vrsto; vsaka nit je demon (ne bo vzdrževala procesa, če se glavna nit konča - to je bolj pogosto kot ne); glavna nit zažene vse podniti, izvede
get
na čakalno vrsto in počaka, da ena od njih izvedeput
, nato pošlje rezultate in se konča (s tem se končajo vse podniti, ki morda še tečejo, saj so niti demoni).Pravilna uporaba niti v Pythonu je vedno povezana z vhodno-izhodnimi operacijami (ker CPython tako ali tako ne uporablja več jeder za izvajanje nalog, vezanih na procesor, je edini razlog za uporabo niti ta, da ne blokira procesa, medtem ko se čaka na kakšen vhodno-izhodni postopek). Čakalne vrste so skoraj vedno najboljši način za porazdelitev dela na niti in/ali zbiranje rezultatov dela, poleg tega pa so po svoji naravi varne za niti, tako da vam prihranijo skrbi z zaklepanjem, pogoji, dogodki, semaforji in drugimi koncepti usklajevanja/komuniciranja med nitmi.
OPOMBA: Za dejansko paralelizacijo v Pythonu morate uporabiti modul multiprocessing za razdvajanje več procesov, ki se izvajajo vzporedno (zaradi globalne blokade tolmača niti v Pythonu omogočajo prepletanje, vendar se dejansko izvajajo zaporedno in ne vzporedno, zato so uporabne le pri prepletanju I/O operacij).
Če pa iščete le prepletanje (ali izvajate operacije I/O, ki jih je kljub globalni blokadi tolmača mogoče vzporediti), potem je modul threading pravi začetek. Kot zelo preprost primer si oglejmo problem seštevanja velikega razpona z vzporednim seštevanjem podrazponov:
Upoštevajte, da je zgornji primer zelo neumen, saj ne izvaja popolnoma nobenega vnosa/iznosa in se bo v CPythonu zaradi globalne blokade prevajalnika izvajal zaporedno, čeprav izmenično (z dodatnimi režijskimi stroški preklapljanja konteksta).
Kot so omenili drugi, lahko CPython zaradi GIL uporablja niti samo za čakanje na I\O. Če želite izkoristiti več jeder za naloge, vezane na procesor, uporabite multiprocessing: