You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中读取stdin后如何正常使用input()?

NetCat脚本中input()异常的原因解析

问题背景

下面是一段NetCat工具的Python脚本:

#!/usr/bin/env python3

import argparse
import socket
import shlex
import subprocess
import sys
import textwrap
import threading

def execute(cmd):
    cmd = cmd.strip()
    if not cmd:
        return
    output = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT)
    return output.decode()

class NetCat:
    def __init__(self, args, buffer=None):
        self.args = args
        self.buffer = buffer
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    def run(self):
        if self.args.listen:
            self.listen()
        else:
            self.send()

    def send(self):
        self.socket.connect((self.args.target, self.args.port))
        if self.buffer:
            self.socket.send(self.buffer)
            
        try:
            while True:
                recv_len = 1
                response = ''
                while recv_len:
                    data = self.socket.recv(4096)
                    recv_len = len(data)
                    response += data.decode()
                    if recv_len < 4096:
                        break
                if response:
                    print(response)
                    buffer = input('> ') #input does not return after new line or even EOF (ctrl-d)
                    buffer += '\n'
                    self.socket.send(buffer.encode())
        except KeyboardInterrupt:
            print('User terminated.')
            self.socket.close()
            sys.exit()

    def listen(self):
        pass


if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Net Tool',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=textwrap.dedent(
        '''Examples:
        netcat.py -t 192.168.1.108 -p 5555 -l -c # command shell
        netcat.py -t 192.168.1.108 -p 5555 -l -u=mytest.txt # upload to file
        netcat.py -t 192.168.1.108 -p 5555 -l -e=\"cat /etc/passwd\" # execute command
        echo 'ABC' | ./netcat.py -t 192.168.1.108 -p 135 # echo text to server port 135
        netcat.py -t 192.168.1.108 -p 5555 # connect to server
        '''
        )
    )
    parser.add_argument('-c', '--command', action='store_true', help='command shell')
    parser.add_argument('-e', '--execute', help='execute specified command')
    parser.add_argument('-l', '--listen', action='store_true', help='listen')
    parser.add_argument('-p', '--port', type=int, default=5555, help='specified port')
    parser.add_argument('-t', '--target', default='127.0.0.1', help='specified IP')
    parser.add_argument('-u', '--upload', help='upload file')
    args = parser.parse_args()
    if args.listen:
        buffer = ''
    else:
        buffer = sys.stdin.read() # stdin is used here, but should that change behaviour of subsequence reading - input() ?
    nc = NetCat(args, buffer.encode())
    nc.run()

执行脚本时遇到以下异常:

  • 执行input('> ')后,无论输入换行还是EOF(Ctrl+D),语句均无法返回;
  • 通过管道重定向stdin(如$ echo 'ABC' | python3 test.py -p 9998)时,input()直接抛出EOFError: EOF when reading a line,无提示符出现。

触发场景:

  1. 无输入触发:执行$ python3 test.py -p 9998,发送消息后出现'> '提示符,但输入新消息后无响应;
  2. 重定向stdin触发:发送ABC后直接抛出EOFError,无提示符。

核心原因:stdin流被sys.stdin.read()耗尽

sys.stdin.read()的行为是一次性读取整个标准输入流的所有内容,直到遇到EOF(文件结束符)。一旦执行这个操作,stdin流的读取指针会移动到流的末尾,后续对该流的读取操作(包括input())会面临两种情况:

1. 重定向stdin场景(如管道输入)

当用echo 'ABC' | python3 test.py -p 9998时,echo输出的内容就是整个stdin流的全部数据。sys.stdin.read()会一次性读完所有内容,此时stdin流直接到达EOF状态。后续调用input()时,因为没有更多内容可以读取,直接抛出EOFError,自然不会显示提示符。

2. 交互式终端场景

当执行python3 test.py -p 9998时,sys.stdin.read()会一直等待用户输入,直到用户按下Ctrl+D(触发EOF)才会返回。此时:

  • 若用户在按下Ctrl+D前输入了内容,这些内容会被全部读取到buffer中并发送给服务器;
  • 但sys.stdin.read()执行完毕后,stdin流的指针停在EOF位置。后续调用input()时,虽然终端还能接收用户输入,但Python的stdin流已经处于EOF状态,input()无法正确读取新输入的内容,表现为输入后无响应。

本质上,sys.stdin是一个单向的字节流,一旦被读取到EOF,后续读取操作要么立即返回EOF(触发异常),要么无限等待永远不会到来的新数据。而input()依赖于从stdin流中读取完整的一行,当流已耗尽时,自然无法正常工作。


内容的提问来源于stack exchange,提问作者milanHrabos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 04:54:53