Próbuję przenieść skrypt powłoki do znacznie bardziej czytelnej wersji Pythona. Oryginalny skrypt powłoki uruchamia w tle kilka procesów (programy narzędziowe, monitory itp.) Za pomocą „&”. Jak mogę osiągnąć ten sam efekt w Pythonie? Chciałbym, aby te procesy nie umarły po zakończeniu skryptów Pythona. Jestem pewien, że ma to jakoś związek z koncepcją demona, ale nie mogłem znaleźć łatwego sposobu.
295
subprocess.Popen()
to nowy zalecany sposób od 2010 r. (Jesteśmy teraz w 2015 r.) I (3) zduplikowane pytanie przekierowujące tutaj również ma akceptowaną odpowiedź na tematsubprocess.Popen()
. Pozdrawiam :-)subprocess.Popen("<command>")
w pliku <command> prowadzonym przez odpowiedni shebang. Działa idealnie dla mnie (Debian) ze skryptami bash i python, domyślnieshell
si przetrwa proces nadrzędny.stdout
idzie do tego samego terminalu, co rodzic. To działa podobnie jak&
w powłoce, która była żądaniem OP. Ale do diabła, wszystkie pytania działają bardzo skomplikowane, a krótkie testy pokazały to wOdpowiedzi:
Uwaga : ta odpowiedź jest mniej aktualna niż w momencie opublikowania w 2009 roku. Korzystanie z
subprocess
modułu przedstawionego w innych odpowiedziach jest teraz zalecane w dokumentacjiJeśli chcesz, aby proces rozpoczął się w tle, możesz użyć go
system()
i wywołać w taki sam sposób, jak skrypt powłoki lub możeszspawn
:(lub alternatywnie możesz wypróbować mniej przenośną
os.P_NOWAIT
flagę).Zobacz dokumentację tutaj .
źródło
subprocess
dać nam wskazówkę, jak odłączyć processubprocess
?Podczas gdy rozwiązanie jkp działa, nowszym sposobem robienia rzeczy (i zaleceniami dokumentacji) jest użycie
subprocess
modułu. W przypadku prostych poleceń jest to odpowiednik, ale oferuje więcej opcji, jeśli chcesz zrobić coś skomplikowanego.Przykład twojej sprawy:
To będzie działać
rm -r some.file
w tle. Zauważ, że wywołanie.communicate()
zwróconego obiektuPopen
będzie blokować, dopóki się nie zakończy, więc nie rób tego, jeśli chcesz, aby działał w tle:Zobacz dokumentację tutaj .
Należy również wyjaśnić: „Tło”, kiedy go używasz, jest wyłącznie koncepcją powłoki; technicznie masz na myśli to, że chcesz odrodzić proces bez blokowania go podczas oczekiwania na jego zakończenie. Jednak użyłem tutaj „tła”, aby odnieść się do zachowania przypominającego tło powłoki.
źródło
Popen()
aby uniknąć blokowania głównego wątku, a jeśli potrzebujesz demona, spójrz napython-daemon
pakiet, aby zrozumieć, jak powinien zachowywać się dobrze zdefiniowany demon. Twoja odpowiedź jest poprawna, jeśli usuniesz wszystko zaczynające się od „Ale bądź ostrożny”, z wyjątkiem linku do dokumentów podprocesu.Prawdopodobnie potrzebujesz odpowiedzi na „Jak wywołać zewnętrzne polecenie w Pythonie” .
Najprostszym podejściem jest użycie
os.system
funkcji, np .:Zasadniczo wszystko, co przekażesz do
system
funkcji, zostanie wykonane tak samo, jakbyś przekazał ją do powłoki w skrypcie.źródło
Znalazłem to tutaj :
W systemie Windows (Win XP) proces nadrzędny nie zakończy się, dopóki
longtask.py
nie zakończy pracy. To nie jest to, czego chcesz w skrypcie CGI. Problem nie jest specyficzny dla Pythona, w społeczności PHP problemy są takie same.Rozwiązaniem jest przekazanie
DETACHED_PROCESS
flagi tworzenia procesu do podstawowejCreateProcess
funkcji w win API. Jeśli akurat masz zainstalowany pywin32, możesz zaimportować flagę z modułu win32process, w przeciwnym razie powinieneś ją zdefiniować samodzielnie:źródło
Używaj
subprocess.Popen()
zclose_fds=True
parametrem, który pozwoli odłączyć spawnowany podproces od samego procesu Pythona i kontynuować działanie nawet po wyjściu z Pythona.https://gist.github.com/yinjimmy/d6ad0742d03d54518e9f
źródło
Prawdopodobnie chcesz rozpocząć badanie modułu os w celu tworzenia różnych wątków (otwierając sesję interaktywną i udzielając pomocy (os)). Odpowiednimi funkcjami są fork i dowolne z nich. Aby dać ci pomysł, jak zacząć, umieść coś takiego w funkcji wykonującej rozwidlenie (funkcja musi wziąć listę lub krotkę „argumenty” jako argument zawierający nazwę programu i jego parametry; możesz również chcieć aby zdefiniować standardowe wejście, wyjście i błąd dla nowego wątku):
źródło
os.fork()
jest naprawdę przydatny, ale ma znaczącą wadę, ponieważ jest dostępny tylko na * nix.threading
: stackoverflow.com/a/53751896/895245 Myślę, że to może działać w systemie Windows.Oba wychwytują dane wyjściowe i działają w tle za pomocą
threading
Jak wspomniano w tej odpowiedzi , jeśli przechwycisz wynik za pomocą,
stdout=
a następnie spróbujeszread()
, proces zostanie zablokowany.Są jednak przypadki, w których jest to potrzebne. Na przykład chciałem uruchomić dwa procesy, które rozmawiają przez port między nimi , i zapisać ich stdout w pliku dziennika i stdout.
threading
Moduł pozwala nam to zrobić.Najpierw spójrz na to, jak wykonać część przekierowania wyjścia samodzielnie w tym pytaniu: Python Popen: Zapisuj jednocześnie do standardowego pliku dziennika AND
Następnie:
main.py
sleep.py
Po bieganiu:
stdout jest aktualizowany co 0,5 sekundy dla każdych dwóch wierszy, które zawierają:
a każdy plik dziennika zawiera odpowiedni dziennik dla danego procesu.
Inspirowany przez: https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/
Testowane na Ubuntu 18.04, Python 3.6.7.
źródło