[python] Stopky

Petr Messner petr.messner na gmail.com
Pátek Říjen 22 16:47:56 CEST 2010


Ahoj,

pokud chceš čekání na vstup omezit nějakým časovým intervalem, máš
několik možností:

1) nastavit si alarm(), operační systém (funguje to na unixech) ti po
uplynutí zadané doby pošle SIGALRM, který nějak patřičně ošetříš,

2) spustit další vlákno, to na danou dobu uspat (time.sleep()), které
po probuzení případně přeruší to první vlákno; toto by bylo nejlepší
řešení, protože by fungovalo i ve Windows - Python ovšem pokud vím (a
co jsem byl schopen dohledat) neumožňuje přerušit vlákno a možná ani
přerušit syscall, na kterém dané vlákno zrovna "stojí" (dá se to
trochu obejít pomocí signal handlerů nebo hacků přes ctypes a C API,
to už je ale lepší řešení 1)),

3) použít neblokující čtení; to bys pak volal stále dokola, dokud by
neuplynulo těch 5 minut (to není moc dobré, ale asi nejjednodušší na
implementaci; opět zřejmě jen pro unix),

4) použít něco jiného, nejspíš dost exotického, třeba pokud tvůj
operační systém přímo nabízí nějaké asynchronní I/O,

4.5) ve Windows: msvcrt
(http://docs.python.org/library/msvcrt.html#console-i-o),

ale nejelegantnější bude

5) použít select nebo pollování (poll, epoll atd.), v tomto případě
bohatě stačí select. Je to funkce, které dáš jako parametry file
deskriptory (případně v Pythonu file objekty) a volitelným parametrem
je čas, po který bude select čekat. Funkce se přeruší v případě, že
uplyne daný timeout, nebo že se na daném vstupu objeví nějaká data. Je
to široce používaná technika - od právě čekání na vstup od uživatele
až po výkonné síťové servery. Je tu akorát problém s Windows a
OpenVMS, kde select funguje jen na socketech. Možná ale půjde
vygooglit, jak to obejít, případně pro Windows použít výše zmíněné
msvcrt.

Viz tedy pydoc select a také man select_tut. Zkusím uvést nějaký ukázkový kód:

#!/usr/bin/env python

import fcntl
import os
import select
import sys

timeout = 300  # 5 minut

# make stdin a non-blocking file
fl = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, fl | os.O_NONBLOCK)

while True:
   (rlist, wlist, xlist) = select.select([sys.stdin], [], [], timeout)
   print rlist
   if rlist:
       print "Bylo zadano: %r" % sys.stdin.read()
   else:
       print "Cas vyprsel"
       break

Snad jsem odpověděl, na co jsi se ptal.


Petr Messner

2010/10/22 remixus79 <remixus79 na gmail.com>:
> Zdravím,
>
> potreboval by som poradiť. Mám program v ktorom je nekonečný cyklus.
> Tento cyklus stale caka na vstup od uzivatela. Potreboval by som to
> spraviť tak že by stále čakal na ten vstup ale zároveň by aj
> kontroloval čas a ak by užívateľ nič nezadal po 5minútach by sa
> vypol.
>
>
> Ďakujem za každú radu.
> _______________________________________________
> Python mailing list
> Python na py.cz
> http://www.py.cz/mailman/listinfo/python
>


Další informace o konferenci Python