Muszę asynchronicznie uruchomić polecenie powłoki ze skryptu w języku Python. Rozumiem przez to, że chcę, aby mój skrypt Pythona działał dalej, podczas gdy zewnętrzne polecenie wyłącza się i robi wszystko, co musi.
Przeczytałem ten post:
Potem wyszedłem i zrobiłem kilka testów i wygląda na to, że os.system()
wykona pracę, pod warunkiem, że użyję &
na końcu polecenia, aby nie musieć czekać na jego powrót. Zastanawiam się, czy jest to właściwy sposób osiągnięcia czegoś takiego? Próbowałem commands.call()
ale u mnie to nie zadziała bo blokuje się na zewnętrzne polecenie.
Daj mi znać, jeśli użycie os.system()
w tym celu jest wskazane lub jeśli powinienem spróbować innej trasy.
źródło
Jeśli chcesz uruchomić wiele procesów równolegle, a następnie obsłużyć je, gdy przyniosą wyniki, możesz użyć sondowania, jak poniżej:
Przepływ sterowania jest trochę zawikłany, ponieważ staram się go zmniejszyć - możesz dostosować go do swojego gustu. :-)
Ma to tę zaletę, że najpierw obsługuje żądania wczesnego kończenia. Jeśli wywołasz
communicate
pierwszy działający proces i okaże się, że działa on najdłużej, pozostałe uruchomione procesy będą bezczynne, podczas gdy mógłbyś obsługiwać ich wyniki.źródło
os.waitpid
bezpośrednio, który pozwala sprawdzić, czy jakiś proces potomny zmienił swój status.['/usr/bin/my_cmd', '-i', path]
zamiast['/usr/bin/my_cmd', '-i %s' % path]
Zastanawiam się, czy to [os.system ()] jest właściwym sposobem osiągnięcia czegoś takiego?
Nie,
os.system()
to nie jest właściwy sposób. Dlatego wszyscy mówią, aby używaćsubprocess
.Aby uzyskać więcej informacji, przeczytaj http://docs.python.org/library/os.html#os.system
źródło
Odniosłem dobry sukces z modułem asyncproc , który ładnie radzi sobie z danymi wyjściowymi z procesów. Na przykład:
źródło
Użycie pexpect z nieblokującymi readlines to kolejny sposób na zrobienie tego. Pexpect rozwiązuje problemy z zakleszczeniem, umożliwia łatwe uruchamianie procesów w tle i zapewnia łatwe sposoby wywoływania zwrotów, gdy proces wypluwa predefiniowane ciągi i ogólnie ułatwia interakcję z procesem.
źródło
Biorąc pod uwagę „Nie muszę czekać, aż wróci”, jednym z najłatwiejszych rozwiązań będzie:
Ale ... Z tego, co przeczytałem, nie jest to „właściwy sposób osiągnięcia czegoś takiego” z powodu zagrożeń bezpieczeństwa, jakie stwarza
subprocess.CREATE_NEW_CONSOLE
flagę.Najważniejsze, co się tutaj dzieje, to użycie programu
subprocess.CREATE_NEW_CONSOLE
do tworzenia nowej konsoli i.pid
(zwraca identyfikator procesu, abyś mógł później sprawdzić program, jeśli chcesz), aby nie czekać, aż program zakończy swoje zadanie.źródło
Mam ten sam problem podczas próby połączenia się z terminalem 3270 za pomocą oprogramowania skryptowego s3270 w języku Python. Teraz rozwiązuję problem z podklasą Process, którą znalazłem tutaj:
http://code.activestate.com/recipes/440554/
A oto próbka pobrana z pliku:
źródło
Przyjęta odpowiedź jest bardzo stara.
Znalazłem tutaj lepszą nowoczesną odpowiedź:
https://kevinmccarthy.org/2016/07/25/streaming-subprocess-stdin-and-stdout-with-asyncio-in-python/
i wprowadził kilka zmian:
Jest mało prawdopodobne, aby przykładowe polecenia działały idealnie w twoim systemie i nie obsługują dziwnych błędów, ale ten kod demonstruje jeden sposób uruchamiania wielu podprocesów przy użyciu asyncio i przesyłania strumieniowego danych wyjściowych.
źródło
wait()
jest przestarzałeJest tutaj kilka odpowiedzi, ale żadna z nich nie spełniła moich poniższych wymagań:
Nie chcę czekać na zakończenie polecenia ani zaśmiecać mojego terminala wyjściami podprocesu.
Chcę uruchomić skrypt bash z przekierowaniami.
Chcę obsługiwać potokowanie w moim skrypcie bash (na przykład
find ... | tar ...
).Jedyną kombinacją, która spełnia powyższe wymagania, jest:
źródło
Jest to omówione w przykładach podprocesów w Pythonie 3 w sekcji „Czekaj, aż polecenie zakończy asynchronicznie”:
Proces rozpocznie się natychmiast po
await asyncio.create_subprocess_exec(...)
zakończeniu. Jeśli nie zakończy się do czasu, gdy zadzwoniszawait proc.communicate()
, będzie tam czekał, aby przekazać ci status wyjścia. Jeśli się skończy,proc.communicate()
wróci natychmiast.Istota tutaj jest podobna do odpowiedzi Terrelsa ale myślę, że odpowiedź Terrelsa wydaje się nadmiernie skomplikować.
Zobacz,
asyncio.create_subprocess_exec
aby uzyskać więcej informacji.źródło