如何从控制台中的python中读取一行?

时间:2016-08-08 14:20:53

标签: python console python-asyncio

我想使用一行代码来读取我在控制台中输入的内容,以便与python中的asyncio模块一起使用。我的代码在从服务器接收数据时打印数据,在完成后,我希望它读取我输入的内容并将其保存到变量中。我不得不使用非标准模块。

有关计划的信息:

  • 目前使用asyncio loop.run_in_executor
  • 读取stdin非阻塞
  • 程序使用loop.create_connection运行,然后使用loop.run_forever并将stdin阅读器添加为任务。

代码:

#!python3.5
#chatroom client

import socket, sys, os, traceback, asyncio
from threading import Lock

DBG = False #More Error printing using full_error function

#async stuf
loop = asyncio.get_event_loop()
lock = Lock()
prev_stdin = ""

#Server Location
target = 'localhost'
port = 17532
buffer_size = 1024
server = None
transports = [] #an array of async.iotransport`s

#Functions for Error handling
full_error = lambda: traceback.print_exception(*sys.exc_info())
pause = lambda: None #make it global for below

#Pause system compatability
if os.name[0:5]=='posix':
    def pause():
        os.system('read -n1 -r -p "Press any key to continue . . ." key')
elif os.name[0:2]=='nt':
    def pause():
        os.system("pause")
else:
    def pause():
        input("Press enter to continue . . .")

def empty_stdin():
    output = ""
    while True:
        temp = sys.stdin.buffer.read(1)
        if temp == "":
            break
        else:
            output += temp
    return output

if DBG:
    loop.set_debug(DBG)

async def write():
    loop = asyncio.get_event_loop()
    while True:
        line = await loop.run_in_executor(None, sys.stdin.readline)
        line = prev_stdin + line
        prev_stdin = ""
        for i in transports:
            loop.call_soon(i.write,line.encode('utf-8'))

class Server(asyncio.Protocol):
    def connection_made(self,transport):
        self.transport = transport
        transport.write(b"Connected")
    def data_received(self, data):
        print("\n%s"%data.decode('utf-8'))
        prev_stdin = empty_stdin()
        print(prev_stdin,)



try:
    coro = loop.create_connection(Server, host=target, port=port)
    task = loop.create_task(coro)
    print("hi")
    print(transports)
    server, serverp = loop.run_until_complete(task)
    transports += [server]
    user_input = loop.create_task(write())
    #loop.add_reader(sys.stdin, write)
    loop.run_forever()
    print('end')

except Exception as e:
    if DBG:
        full_error()
    else:
        print(type(e))
        print(e)
    pause()
    sys.exit()

1 个答案:

答案 0 :(得分:0)

我通过使用msvcrt来捕获单个字符并更改了一些代码来解决问题(仅限Windows)。

新功能/更改

  1. draw_screen:

    • 使用os.system("cls")
    • 清除屏幕
    • 打印我打印信息时保存的行(可能会变得迟钝)
    • 使用我正在键入的内容打印光标(">> Hello")
  2. 写:

    • 用msvcrt.getch替换了sys.stdin.readline
    • 更多更改
  3. 到处:

    • 每当我打印时,将其添加到screen变量中,该变量是包含所有内容的数组。然后它调用draw_screen()
    • 删除了prev_stdin的内容
    • 删除了其他一些打印陈述
  4. 最终守则(目前):

    #!python3.5
    #chatroom client
    
    import sys, os, traceback, asyncio, msvcrt
    from threading import Lock
    
    DBG = False #More Error printing using full_error function
    
    screen = [] #holds lines of text that are printed to the screen
    line = ""
    
    #async stuf
    loop = asyncio.get_event_loop()
    lock = Lock()
    
    
    #Server Location
    target = 'localhost'
    port = 17532
    buffer_size = 1024
    server = None
    transports = [] #an array of async.iotransport`s
    
    #Functions for Error handling
    full_error = lambda: traceback.print_exception(*sys.exc_info())
    
    #system compatable functions
    if os.name[0:5]=='posix':
        def pause():
            os.system('read -n1 -r -p "Press any key to continue . . ." key')
        def cls():
            os.system("clear")
    elif os.name[0:2]=='nt':
        def pause():
            os.system("pause")
        def cls():
            os.system("cls")
    else:
        def pause():
            input("Press enter to continue . . .")
        def cls():
            os.system("clear")
    
    def draw_screen():
        cls()
        for i in screen:
            print(i)
        print("> ", line, end="\r") #Draws current line of text being typed
    
    if DBG:
        loop.set_debug(DBG)
    
    async def write():
        global line
        while True:
            temp = await loop.run_in_executor(None, msvcrt.getch)
            temp = temp.decode('utf-8')
            if temp == "\b":
                line = line[0:len(line)-1]
            elif not (temp == "\r" or temp == "\n"):
                line += temp
            else:
                for i in transports:
                    loop.call_soon(i.write,line.encode('utf-8'))
                line = ""
            draw_screen()
    
    class Server(asyncio.Protocol):
        def connection_made(self,transport):
            self.transport = transport
            transport.write(b"Connected")
        def data_received(self, data):
            global screen
            screen += ["%s"%data.decode('utf-8')]
            draw_screen()
    
    
    
    try:
        coro = loop.create_connection(Server, host=target, port=port)
        task = loop.create_task(coro)
        server, serverp = loop.run_until_complete(task)
        transports += [server]
        user_input = loop.create_task(write())
        loop.run_forever()
        print('end')
    
    except Exception as e:
        if DBG:
            full_error()
        else:
            print(type(e))
            print(e)
        pause()
        sys.exit()