Edit detail for DocasneCekaniNaVstup revision 2 of 1

2
Editor: pycz
Time: 2011/10/15 12:15:20 GMT+2
Note: pridavani znacek 2x-3x

changed:
-
.. image:: py30.png
   :align: right
   
Dočasné čekání na vstup
========================

*Vytaženo a upraveno z konference*

Dotaz
-----
Ahoj, potřebuji aby když uživatel neodpoví na výzvu *input()* do 5 sekund, aby čekání na odpověď skončilo a dosadila se nějaké defaultní hodnota.

Obecná odpověď
-----------------

Zdravím, Nejjednodušší (a nejelegantnější) by bylo použití funkce alarm a obsluhy SIGALRM, ale to je možné pouze na rozumných OS, které vyhovují normě
POSIX (což by správně měly všechny systémy, ale nic není ideální...).
Další možností by bylo použití funkce select, ale to také na OS, který
nejmenujeme, nepůjde (tam funguje select jen se sockety). Možná by šlo
určitým způsobem využít nonblocking IO, ale to by nejspíš vyžadovalo
pywin32 knihovny a nevím, jaká je úroveň podpory této funkce v technicky
nedokonalých systémech. Řešení přes thready mi přijde docela
komplikované a nespolehlivé, hlavně je otázkou přerušení raw_input
funkce (možná by šlo použít něco jako externí interrupt vlákna, ale
taktéž nevím, do jaké míry je tato funkce spolehlivá). Takže odpověď
není jednoznačná, můžete vyzkoušet různé postupy, v případě zájmu o
podrobnosti se ozvěte.

GUI
----
Ne, nepotrebujes input(), potrebujes od uzivatele nejak *zadat
hodnotu*. Tohle upresneni je pomerne zasadni :). Preruseni input()
muze byt IMHO totiz pomerne problematicke. Na Tvem miste bych zkusil
pouzit nejaky toolkit pro vytvareni TUI (textovych user interface),
treba (n)curses nebo slang nebo GUI (Tkinter, PyGTK, ...).

Windows
--------
Není bez chyby, není takový jaký by měl, ale alespon neco. Jakmile 
napíšeš jediné písmeno, už není možno ukončit vlákno po zadané době. Problém totiž je, že nejde násilně ukončit vlákno, které čeká na obyčejném *input()*

::
  
  import threading, queue, time
  import msvcrt # Jen pro MS Windows
  
  vystup = queue.Queue()
  zamek = threading.Lock()
  
  def vlakno1():
      time.sleep(5)
      vystup.put('konec')
  
  def vlakno2():
      print ("Ocekavam vstup: ")
      while nasloucham.isAlive():
          if msvcrt.kbhit():
              zamek.acquire()
              vystup.put(input())
              zamek.release()
  
  nasloucham = threading.Thread(target = vlakno1)
  cekamvstup = threading.Thread(target = vlakno2)
  nasloucham.start()
  cekamvstup.start()
  while nasloucham.isAlive() or not vystup.empty():
      if not zamek.locked() and not vystup.empty():
          print (vystup.get() )

Linux
------
Zaprvé píšu s křížkem po funuse a zadruhé tohle řešení bude fungovat jen 
na Operačních systémech, což už poznamenal regnarG. Takže si toho 
nevšímejte  :-) :: 

   #!/usr/bin/python
  
   import sys, select
   r = select.select([sys.stdin], [], [], 5)
   if r[0]:
        choice = sys.stdin.readline()
   else:
        choice = 'default\n'
   print 'Tvoje volba:', choice





py30.png

Dočasné čekání na vstup

Vytaženo a upraveno z konference

Dotaz

Ahoj, potřebuji aby když uživatel neodpoví na výzvu input() do 5 sekund, aby čekání na odpověď skončilo a dosadila se nějaké defaultní hodnota.

Obecná odpověď

Zdravím, Nejjednodušší (a nejelegantnější) by bylo použití funkce alarm a obsluhy SIGALRM, ale to je možné pouze na rozumných OS, které vyhovují normě POSIX (což by správně měly všechny systémy, ale nic není ideální...). Další možností by bylo použití funkce select, ale to také na OS, který nejmenujeme, nepůjde (tam funguje select jen se sockety). Možná by šlo určitým způsobem využít nonblocking IO, ale to by nejspíš vyžadovalo pywin32 knihovny a nevím, jaká je úroveň podpory této funkce v technicky nedokonalých systémech. Řešení přes thready mi přijde docela komplikované a nespolehlivé, hlavně je otázkou přerušení raw_input funkce (možná by šlo použít něco jako externí interrupt vlákna, ale taktéž nevím, do jaké míry je tato funkce spolehlivá). Takže odpověď není jednoznačná, můžete vyzkoušet různé postupy, v případě zájmu o podrobnosti se ozvěte.

GUI

Ne, nepotrebujes input(), potrebujes od uzivatele nejak zadat hodnotu. Tohle upresneni je pomerne zasadni :). Preruseni input() muze byt IMHO totiz pomerne problematicke. Na Tvem miste bych zkusil pouzit nejaky toolkit pro vytvareni TUI (textovych user interface), treba (n)curses nebo slang nebo GUI (Tkinter, PyGTK, ...).

Windows

Není bez chyby, není takový jaký by měl, ale alespon neco. Jakmile napíšeš jediné písmeno, už není možno ukončit vlákno po zadané době. Problém totiž je, že nejde násilně ukončit vlákno, které čeká na obyčejném input()

import threading, queue, time
import msvcrt # Jen pro MS Windows

vystup = queue.Queue()
zamek = threading.Lock()

def vlakno1():
    time.sleep(5)
    vystup.put('konec')

def vlakno2():
    print ("Ocekavam vstup: ")
    while nasloucham.isAlive():
        if msvcrt.kbhit():
            zamek.acquire()
            vystup.put(input())
            zamek.release()

nasloucham = threading.Thread(target = vlakno1)
cekamvstup = threading.Thread(target = vlakno2)
nasloucham.start()
cekamvstup.start()
while nasloucham.isAlive() or not vystup.empty():
    if not zamek.locked() and not vystup.empty():
        print (vystup.get() )

Linux

Zaprvé píšu s křížkem po funuse a zadruhé tohle řešení bude fungovat jen na Operačních systémech, což už poznamenal regnarG. Takže si toho nevšímejte :-)

#!/usr/bin/python

import sys, select
r = select.select([sys.stdin], [], [], 5)
if r[0]:
     choice = sys.stdin.readline()
else:
     choice = 'default\n'
print 'Tvoje volba:', choice