2010-03-09 19 views
31

मैं पाइथन में एक साधारण आईआरसी क्लाइंट बनाने की कोशिश कर रहा हूं (जैसा कि मैं भाषा सीखता हूं)।पायथन गैर-कंसोलिंग कंसोल इनपुट

मेरे पास एक लूप है जिसे मैं आईआरसी सर्वर भेजता हूं और प्राप्त करने के लिए उपयोग करता हूं, लेकिन यदि मैं इनपुट सामग्री के लिए raw_input का उपयोग करता हूं, तो यह लूप को अपने ट्रैक में तब तक रोक देता है जब तक कि मैं कुछ इनपुट (स्पष्ट रूप से) इनपुट नहीं करता।

मैं लूप को रोकने के बिना कुछ कैसे इनपुट कर सकता हूं?

अग्रिम धन्यवाद।

(मुझे नहीं लगता कि मैं कोड पोस्ट करने के लिए की जरूरत है, मैं सिर्फ जबकि 1 पाश रोक के बिना इनपुट कुछ करना चाहते हैं।)

संपादित करें: मैं विंडोज पर कर रहा हूँ।

+2

मैंने विंडोज़ विशिष्ट उदाहरण के साथ अपना जवाब अपडेट किया। – Mizipzor

+0

आप किस नेटवर्किंग मॉड्यूल का उपयोग कर रहे थे? मुड़, सॉकेट, asyncore? – DevPlayer

उत्तर

34

Windows के लिए, कंसोल केवल, 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 

लिनक्स के लिए, यह article निम्नलिखित समाधान का वर्णन करता है, यह 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) 

क्रॉस प्लेटफॉर्म के लिए, या यदि आप एक जीयूआई भी चाहते हैं, तो आप 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 
+0

मेरे पास पहले से ही pygame है, इसलिए मैं इसे आज़माउंगा। धन्यवाद। फिर भी, क्या किसी और के पास कोई बेहतर समाधान है? मैं इसे एक कंसोल रखना चाहता हूं। – ImTooStupidForThis

+0

msvcrt सामान के लिए धन्यवाद। आप कमाल के है। – ImTooStupidForThis

+0

सहायता के लिए खुश होना, स्टैक ओवरफ्लो में आपका स्वागत है। :) – Mizipzor

8

लिनक्स पर, यहां मिज़िपोजर के कोड का एक रिफैक्टरिंग है जो इसे थोड़ा आसान बनाता है, अगर आपको इस कोड को कई स्थानों पर उपयोग करना है।

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 

यहां इसका उपयोग कैसे करें: यह कोड एक काउंटर प्रिंट करेगा जो तब तक बढ़ता रहता है जब तक आप ईएससी दबाते हैं।

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

जीएनयू/लिनक्स का उपयोग करना: आपको अभी भी एक चरित्र दर्ज करने के बाद एंटर दबाएं, लेकिन फिर यह काम करता है। कम से कम यह गैर-अवरुद्ध है और यह आमतौर पर सामान्य पात्रों को लौटाता है (कोई कुंजीकोड नहीं, विशेष कुंजी से बचें जैसे पाठ्यक्रम से बचें या बैकस्पेस)। धन्यवाद! – Luc

9

यहाँ कि लिनक्स और विंडोज के अधीन ही एक अलग धागे का उपयोग कर एक समाधान:

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() 
+0

यहां एकमात्र समाधान होने लगता है जो विंडोज सेमीड-कंसोल और ग्रहण में दोनों काम करता है! –

15

यह सबसे भयानक solution मैंने आज तक देखा है। मामले कड़ी में यहाँ पेस्ट किया गया नीचे चला जाता है:

#!/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() 

Simon D. Levy द्वारा बनाया गया, एक compilation of software का हिस्सा वह लिखा और Gnu Lesser General Public License के तहत जारी किया है।

1

python3.3 के साथ और आप asyncio मॉड्यूल के रूप में इस जवाब में बताया गया उपयोग कर सकते हैं इसके बाद के संस्करण। asyncio के साथ काम करने के लिए आपको अपने कोड को फिर से कारगर करना होगा। Prompt for user input using python asyncio.create_server instance

2

मुझे लगता है कि श्राप पुस्तकालय मदद कर सकता है।

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() 
+0

श्राप पोर्टेबल नहीं है। – kfsone

संबंधित मुद्दे