Jak na zawsze uruchomić program w Pythonie?

87

Muszę uruchamiać program w języku Python w nieskończonej pętli.

Obecnie prowadzę to w ten sposób -

#!/usr/bin/python

import time

# some python code that I want 
# to keep on running


# Is this the right way to run the python program forever?
# And do I even need this time.sleep call?
while True:
    time.sleep(5)

Czy jest lepszy sposób na zrobienie tego? A może nawet muszę time.sleepzadzwonić? jakieś pomysły?

Alan W. Smith
źródło
To byłby właściwy sposób na zrobienie tego. Nie potrzebujesz time.sleep(5), o ile masz jakiś kod wcięty poniżej while True:linii (może to być passminimum)
Holy Mackerel
1
Dobrze jest dodać warunek przerwania - „hak zamykający”, jeśli chcesz wyjść, zamiast zabijać proces.
user3020494
7
Ale jeśli nie śpisz lub robisz coś, co śpi z powodu zdarzenia zewnętrznego (np . Nasłuchiwanie połączeń lub danych w gnieździe), twój program będzie używać 100% procesora, czyli busywait . To nie jest grzeczne :)
qris
Python 3.5 może używać funkcji asyncio i wiązać funkcje ze zdarzeniami. Program z GUI radzi sobie z pętlą zdarzeń ui (na przykład gtk.main ())
eri
Wygląda na to, że jest to duplikat tego pytania: stackoverflow.com/questions/3226628/non-blocking-wait-in-python
dllahr

Odpowiedzi:

104

Tak, możesz użyć while True: pętli, która nigdy się nie zrywa, aby stale uruchamiać kod Pythona.

Będziesz jednak musiał umieścić kod, który chcesz stale uruchamiać, wewnątrz pętli:

#!/usr/bin/python

while True:
    # some python code that I want 
    # to keep on running

Ponadto, time.sleepstosuje się zawiesić działanie skryptu na pewien okres czasu. Tak więc, skoro chcesz, aby Twój działał nieprzerwanie, nie rozumiem, dlaczego miałbyś go używać.


źródło
podczas gdy True nie działa podczas uruchamiania kodu Pythona za pomocą pliku .bat
BarryMahnly
2
Czy można time.sleeppoprawić wydajność, czekając na przykład 1 ms zamiast pracować z maksymalną prędkością?
538ROMEO
36

A co z tym?

import signal
signal.pause()

Pozwoli to programowi spać, dopóki nie otrzyma sygnału z innego procesu (lub samego siebie, w innym wątku), informując go, że nadszedł czas, aby coś zrobić.

ryczeć
źródło
2
Sygnał zatrzyma wątek. Tytuł dotyczy ciągłego biegania. Podobnie jak usługa systemowa lub demon.
poza domem
1
czy zatrzymałoby to tylko główny wątek, pozwalając innym na działanie w nieskończoność?
David V.
@David Tak, to zatrzymuje tylko główny wątek. Właśnie przetestowałem, aby potwierdzić.
Samuel
9

spanie to dobry sposób na uniknięcie przeciążenia procesora

Nie jestem pewien, czy to naprawdę sprytne, ale zwykle używam

while(not sleep(5)):
    #code to execute

metoda uśpienia zawsze zwraca wartość None.

Porunga
źródło
odrzucony bez komentarza? Podobało mi się to rozwiązanie, gdy je czytam, ponieważ ma dobrą czytelność / łatwość utrzymania. Zainteresowany czytelnik tego kodu nie musi przewijać, aby znaleźć interwał pętli.
Matt,
1
@mustafa który z nich? wytłumacz się, działa doskonale.
Porunga,
1
czy nie śpi przed pierwszą egzekucją? Nie sądzę, żeby było to pożądane zachowanie w ogóle
południe
7

Wiem, że to zbyt stary wątek, ale dlaczego nikt o tym nie wspomniał

#!/usr/bin/python3
import asyncio 

loop = asyncio.get_event_loop()
try:
    loop.run_forever()
finally:
    loop.close()
Edge Goldberg
źródło
1
Zawsze używam tego, gdy próbuję sprawić, by mój program działał wiecznie. Nie wiem, dlaczego nikt o tym nie wspomniał
madladzen
5

dla systemów operacyjnych, które obsługują select:

import select

# your code

select.select([], [], [])
gnr
źródło
5

Oto pełna składnia,

#!/usr/bin/python3

import time 

def your_function():
    print("Hello, World")

while True:
    your_function()
    time.sleep(10) #make function to sleep for 10 seconds
Balaji.JB
źródło
1

Mam mały skrypt interruptableloop.py, który uruchamia kod w odstępach czasu (domyślnie 1 sekunda), wypompowuje wiadomość na ekran podczas działania i przechwytuje sygnał przerwania, który możesz wysłać za pomocą CTL-C:

#!/usr/bin/python3
from interruptableLoop import InterruptableLoop

loop=InterruptableLoop(intervalSecs=1) # redundant argument
while loop.ShouldContinue():
   # some python code that I want 
   # to keep on running
   pass

Po uruchomieniu skryptu, a następnie przerwaniu go, zobaczysz następujące dane wyjściowe (okresy wypompowują się przy każdym przejściu pętli):

[py36]$ ./interruptexample.py
CTL-C to stop   (or $kill -s SIGINT pid)
......^C
Exiting at  2018-07-28 14:58:40.359331

przerywalnaLoop.py :

"""
    Use to create a permanent loop that can be stopped ...

    ... from same terminal where process was started and is running in foreground: 
        CTL-C

    ... from same user account but through a different terminal 
        $ kill -2 <pid> 
        or $ kill -s SIGINT <pid>

"""
import signal
import time
from datetime import datetime as dtt
__all__=["InterruptableLoop",]
class InterruptableLoop:
    def __init__(self,intervalSecs=1,printStatus=True):
        self.intervalSecs=intervalSecs
        self.shouldContinue=True
        self.printStatus=printStatus
        self.interrupted=False
        if self.printStatus:
            print ("CTL-C to stop\t(or $kill -s SIGINT pid)")
        signal.signal(signal.SIGINT, self._StopRunning)
        signal.signal(signal.SIGQUIT, self._Abort)
        signal.signal(signal.SIGTERM, self._Abort)

    def _StopRunning(self, signal, frame):
        self.shouldContinue = False

    def _Abort(self, signal, frame):
        raise 

    def ShouldContinue(self):
        time.sleep(self.intervalSecs)
        if self.shouldContinue and self.printStatus: 
            print( ".",end="",flush=True)
        elif not self.shouldContinue and self.printStatus:
            print ("Exiting at ",dtt.now())
        return self.shouldContinue
Riaz Rizvi
źródło
Czy nie byłoby o wiele łatwiej (i bardziej w Pythonie) po prostu wychwycić wyjątki KeyboardInterrupti SystemExitw kodzie klienta, zamiast mieć dla niego dedykowaną klasę?
Matthew Cole
Używam tego do hermetyzacji i podoba mi się sposób, w jaki czyta. Oczywiście implementacja interruptableloop nie przychodzi mi do głowy, kiedy jej używam.
Riaz Rizvi