Come gestire correttamente generatori indefiniti in Python

1

Diciamo che abbiamo un generatore indefinito, in cui i nuovi elementi possono arrivare in qualsiasi momento con un ritardo significativo (fino a un indefinito).

Un esempio di tale generatore è il comando tail -F . In python (omettendo vari casi limite) potrebbe essere implementato come segue:

def tail_follow(file):
    while True:
        line = file.readline()
        if line:
            yield line
        else:
            sleep(1.0)

Il problema ovvio con questo generatore è che può causare il sonno del thread del chiamante per sempre. Pertanto dovrebbe fornire al lato del chiamante un modo per interrompere l'iterazione.

La soluzione che ho trovato è la seguente:

def tail_follow(file, on_delay_callback):
    while True:
        line = file.readline()
        if line:
            yield line
        else:
            if on_delay_callback():
                break
            else:
                sleep(1.0)

Questo è l'unico modo per ottenere questo comportamento con Python? So che esiste una funzione di invio che consente il trasferimento di dati a 2 vie, può essere utilizzata per rendere la soluzione più pitonica?

    
posta Kentzo 05.08.2015 - 18:23
fonte

1 risposta

3

Non vedo il problema con il tuo approccio. Penso che tu sia quasi arrivato. Se cambi il generatore in yield None quando non c'è nulla da restituire, puoi semplicemente testarlo.

Vedi il seguente esempio:

#!/usr/bin/python

import sys
import time

tailpath = "./tailfile"
fd = open(tailpath)

def tail_follow(file):
    while True:
        line = file.readline()
        if line:
            yield line
        else:
            yield None


if __name__ == "__main__":
    for line in tail_follow(fd):
        if line:
            print ("found: %s" % (line))
        else:
            # do something useful
            time.sleep(1.0)

O in alternativa:

if __name__ == "__main__":
    mytail = tail_follow(fd)
    while True:
        # do something useful
        time.sleep(1.0)
        # anything to tail ?
        line = next(mytail)
        if line:
            print ("found: %s" % (line))

Jeff Knupp ha un bel post sui generatori infiniti.

    
risposta data 07.08.2015 - 07:42
fonte

Leggi altre domande sui tag