Keep console input line below output

2019-02-22 17:55发布

[EDIT:] I'm currently trying to make a small tcp chat application. Sending and receiving messages already works fine... But the problem is:

When i start typing a message while i receive one... it appears after the text I'm writing

Screenshot: http://s7.directupload.net/images/140816/6svxo5ui.png

[User sent > "hello", then I started writing "i am writing..." then user wrote " i sent a..." before i sent my message... so it has been placed after my input... I want the incoming message always to be before my input !

this is my current code: Client.py

con = connect.User()
server = raw_input("Type in the server adress \n[leave blank to use xyr.no-ip.info]\n>:")
nick =""

while nick == "":
    nick = raw_input("Type in your nickname\n>:")

con.connect(server, nick)


def sender():
    print("Sender started")
    while 1:
        msg = raw_input()
        if msg == "q":
            break
        con.send(msg)

    con.disconnect()



def receiver(server):

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        if server == "":
            server="xyr.no-ip.info"

        sock.connect((server, 8000))

        sock.send("%pyreceiver\n")

        print("Receiver started")

        while 1:
           msg_in = sock.recv(1024)
           if not str(msg_in).startswith("[py]" + nick):
               if str(msg_in).startswith("/ua"):
                   print(str(msg_in)[3:])

               elif str(msg_in).startswith("/u "):
                   print(str(msg_in)[2:])
               else:

                print(str(msg_in[:-1]))
#

if nick == "":
    nick = "guest"
    print("Name changed to ""guest""")
    time.sleep(.5)

thread.start_new_thread(receiver, (server, ))
time.sleep(.5)
thread.start_new_thread(sender())

Connect.py

import socket

import time

class User():


    nickel =""
    def connect(self, server="xyr.no-ip.info", nick="guest"):
        nickel = nick
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if server == "":
            server="xyr.no-ip.info"
            print("server changed to xyr.no-ip.info")
            time.sleep(.5)


        print("Connecting...")
        self.sock.connect((server, 8000))
        print("Connected")
        time.sleep(.4)
        self.sock.send("[py]" + nick + "\n")


        self.sock.send(nick + " connected with a python client\n")
        print("registered as " + nick)
        time.sleep(.3)


    def send(self, msg):
        self.sock.send(msg + "\n")


    def disconnect(self):
        self.sock.close()

        print("disconnected")

2条回答
看我几分像从前
2楼-- · 2019-02-22 18:01

I had a similar problem and I found that a simpler solution (for me) was to get input via readchar (https://github.com/magmax/python-readchar/tree/master/readchar).

Using readchar, I would buffer each keystroke (checking for key.BACKSPACE and CR - see code snippet below).

All output I would prepend with "/033[1A" (make the cursor move up), print the output line, and then a "/n"...

after each output line, I move the cursor to the beginning and re-print the self.input_buff

while the user is doing input, this handles console input, displaying what they are typing:

            keypress = readkey()

            if keypress == key.BACKSPACE:
                self.input_buff = self.input_buff[:-1]
                print("\033[0A%s         " % self.input_buff)
                continue

            if keypress != key.CR:
                self.input_buff = "%s%s" % (self.input_buff, keypress)
                print("\033[0A%s" %  self.input_buff)
                continue

This kept the input line at the bottom and all terminal output above it.

I know it comes a year late and if you are a wiz with curses, maybe that is the way to go...

查看更多
够拽才男人
3楼-- · 2019-02-22 18:06

Your code writes everything to stdout. Whenever something arrives to either of your sender/receiver threads, it prints to stdout. The issue with that is, due to the fundamental nature of output streams, you cannot accomplish the following :

  • place incoming messages above the stuff currently being typed/echoed.

Things happen strictly in the order of occurrence. The moment something comes in, wherever the cursor is, the print statement dumps that data over there. You cannot modify that behaviour without using fancier / more powerful constructs.

In order to do what you want, I would use ncurses. You seem to be using python on Windows, so you're going to have to do some digging on how to get equivalent functionality. Check out this thread : Curses alternative for windows

查看更多
登录 后发表回答