1

在嵌入 python 解释器的 C 程序中,我通过 TCP 套接字生成了一个 python 交互式控制台。

import socket
import code
import sys

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 2000))
s.listen(1)
c = s.accept()[0] # client socket

def sread(s, len):
        return s.recv(len)
def swrite(s, str):
        return s.sendall(str)
def sreadline(s):
        return sread(s, 256) # lazy implementation for quick testing
socket.socket.read = sread
socket.socket.write = swrite
socket.socket.readline = sreadline
sys.stdin = c
sys.stdout = c
sys.stderr = c
code.interact() # runs the interactive console

这基本上有效。但是,交互式控制台在返回某些用户输入语句的结果时永远不会发出任何行尾字符。换句话说,我们得到这样的东西:

nc localhost 2000
Python 2.7.3 (default, Sep 26 2012, 21:53:55) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 1+1
2>>> 

在解释器响应用户输入“1+1”而发送结果“2”之后,在下一个提示“>>>”之前,我们看不到 CR-LF。通过检查套接字用户端的十六进制输出或检查即将写入套接字的字符串来确认是否缺少任何行尾字符(CR 和/或 LF) swrite( )。

现在为什么交互式控制台没有发出行尾字符?

可以修复吗?如何修复?

4

2 回答 2

1

关于“为什么”的问题仍然悬而未决,但至于如何解决它,这里有解决方案。不要向 socket.socket 类添加 read/write/readline 方法,而是对 socket.socket 类进行包装:

import socket
import code
import sys

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 2000))
s.listen(1)
c = s.accept()[0] # client socket

class sw: # socket wrapper
    def __init__(self, s):
        self.s = s
    def read(self, len):
            return self.s.recv(len)
    def write(self, str):
            return self.s.send(str)
    def readline(self):
            return self.read(256) # lazy implementation for quick testing
c = sw(c)
sys.stdin = c
sys.stdout = c
sys.stderr = c
code.interact() # runs the interactive console

现在这可以按预期工作,但原因不明。

nc localhost 2000
Python 2.7.3 (default, Sep 26 2012, 21:51:14) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 1+1
2
>>>
于 2013-04-22T21:03:03.857 回答
1

这与softspace决定 Python 何时应该发送换行符的文件属性有关,并且需要可写才能使 Python 正常运行。

因为您设置sys.stdout为“只读”套接字对象,所以无法设置该属性,因此您会遇到文本输出问题。

__getattr__您可以通过以与其他方法相同的方式定义 a and方法来修复它__setattr__,但这是一个完整的 hack,因此您最好使用“包装器”解决方案。

于 2013-04-23T11:15:22.760 回答