xticks barplot python windows input

python - barplot - pandas plot



Entrada de consola sin bloqueo de Python (6)

Aquí una solución que se ejecuta en Linux y Windows utilizando un hilo separado:

import sys import threading import time import Queue def add_input(input_queue): while True: input_queue.put(sys.stdin.read(1)) def foobar(): input_queue = Queue.Queue() input_thread = threading.Thread(target=add_input, args=(input_queue,)) input_thread.daemon = True input_thread.start() last_update = time.time() while True: if time.time()-last_update>0.5: sys.stdout.write(".") last_update = time.time() if not input_queue.empty(): print "/ninput:", input_queue.get() foobar()

Estoy intentando hacer un cliente IRC simple en Python (como una especie de proyecto mientras aprendo el idioma).

Tengo un bucle que uso para recibir y analizar lo que el servidor IRC me envía, pero si uso raw_input para ingresar cosas, detiene el bucle muerto en sus pistas hasta que ingrese algo (obviamente).

¿Cómo puedo ingresar algo sin que el ciclo se detenga?

Gracias por adelantado.

(No creo que deba publicar el código, solo quiero ingresar algo sin que se detenga el ciclo 1 ).

EDITAR: estoy en Windows.



Creo que la biblioteca de curses puede ayudar.

import curses import datetime stdscr = curses.initscr() curses.noecho() stdscr.nodelay(1) # set getch() non-blocking stdscr.addstr(0,0,"Press /"p/" to show count, /"q/" to exit...") line = 1 try: while 1: c = stdscr.getch() if c == ord(''p''): stdscr.addstr(line,0,"Some text here") line += 1 elif c == ord(''q''): break """ Do more things """ finally: curses.endwin()


En Linux, aquí hay una refactorización del código de Mizipzor que hace que esto sea un poco más fácil, en caso de que tenga que usar este código en varios lugares.

import sys import select import tty import termios class NonBlockingConsole(object): def __enter__(self): self.old_settings = termios.tcgetattr(sys.stdin) tty.setcbreak(sys.stdin.fileno()) return self def __exit__(self, type, value, traceback): termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.old_settings) def get_data(self): if select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []): return sys.stdin.read(1) return False

Aquí le mostramos cómo usar esto: Este código imprimirá un contador que seguirá creciendo hasta que presione ESC.

with NonBlockingConsole() as nbc: i = 0 while 1: print i i += 1 if nbc.get_data() == ''/x1b'': # x1b is ESC break


Esta es la solution más asombrosa 1 que he visto en mi vida. Pegado aquí en caso de que el enlace se caiga:

#!/usr/bin/env python '''''' A Python class implementing KBHIT, the standard keyboard-interrupt poller. Works transparently on Windows and Posix (Linux, Mac OS X). Doesn''t work with IDLE. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. '''''' import os # Windows if os.name == ''nt'': import msvcrt # Posix (Linux, OS X) else: import sys import termios import atexit from select import select class KBHit: def __init__(self): ''''''Creates a KBHit object that you can call to do various keyboard things. '''''' if os.name == ''nt'': pass else: # Save the terminal settings self.fd = sys.stdin.fileno() self.new_term = termios.tcgetattr(self.fd) self.old_term = termios.tcgetattr(self.fd) # New terminal setting unbuffered self.new_term[3] = (self.new_term[3] & ~termios.ICANON & ~termios.ECHO) termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term) # Support normal-terminal reset at exit atexit.register(self.set_normal_term) def set_normal_term(self): '''''' Resets to normal terminal. On Windows this is a no-op. '''''' if os.name == ''nt'': pass else: termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term) def getch(self): '''''' Returns a keyboard character after kbhit() has been called. Should not be called in the same program as getarrow(). '''''' s = '''' if os.name == ''nt'': return msvcrt.getch().decode(''utf-8'') else: return sys.stdin.read(1) def getarrow(self): '''''' Returns an arrow-key code after kbhit() has been called. Codes are 0 : up 1 : right 2 : down 3 : left Should not be called in the same program as getch(). '''''' if os.name == ''nt'': msvcrt.getch() # skip 0xE0 c = msvcrt.getch() vals = [72, 77, 80, 75] else: c = sys.stdin.read(3)[2] vals = [65, 67, 66, 68] return vals.index(ord(c.decode(''utf-8''))) def kbhit(self): '''''' Returns True if keyboard character was hit, False otherwise. '''''' if os.name == ''nt'': return msvcrt.kbhit() else: dr,dw,de = select([sys.stdin], [], [], 0) return dr != [] # Test if __name__ == "__main__": kb = KBHit() print(''Hit any key, or ESC to exit'') while True: if kb.kbhit(): c = kb.getch() if ord(c) == 27: # ESC break print(c) kb.set_normal_term()

1 Realizado por Simon D. Levy , parte de una compilación de software que ha escrito y publicado bajo la Licencia pública general menor de Gnu .


Para Windows, solo consola, use el módulo msvcrt :

import msvcrt num = 0 done = False while not done: print(num) num += 1 if msvcrt.kbhit(): print "you pressed",msvcrt.getch(),"so now i will quit" done = True

Para Linux, este article describe la siguiente solución, requiere el módulo termios :

import sys import select import tty import termios def isData(): return select.select([sys.stdin], [], [], 0) == ([sys.stdin], [], []) old_settings = termios.tcgetattr(sys.stdin) try: tty.setcbreak(sys.stdin.fileno()) i = 0 while 1: print(i) i += 1 if isData(): c = sys.stdin.read(1) if c == ''/x1b'': # x1b is ESC break finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)

Para plataforma cruzada, o en caso de que también desee una GUI, puede usar Pygame:

import pygame from pygame.locals import * def display(str): text = font.render(str, True, (255, 255, 255), (159, 182, 205)) textRect = text.get_rect() textRect.centerx = screen.get_rect().centerx textRect.centery = screen.get_rect().centery screen.blit(text, textRect) pygame.display.update() pygame.init() screen = pygame.display.set_mode( (640,480) ) pygame.display.set_caption(''Python numbers'') screen.fill((159, 182, 205)) font = pygame.font.Font(None, 17) num = 0 done = False while not done: display( str(num) ) num += 1 pygame.event.pump() keys = pygame.key.get_pressed() if keys[K_ESCAPE]: done = True