在嵌入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。 通过以十六进制检查套接字的用户端的输出,或检查将要在函数swrite中写入套接字的字符串,可以确认没有任何行尾字符(CR和/或LF)( )。
现在为什么交互式控制台没有发出行尾字符?
可以修复吗?
答案 0 :(得分:1)
关于'为什么'的问题仍然存在,但至于如何解决,这里是解决方案。 而不是将read / write / readline方法添加到socket.socket类,而是创建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
>>>
答案 1 :(得分:1)
这与softspace
文件属性有关,它确定Python何时应该发送换行符,并且需要可写,以便Python正常运行。
因为您将sys.stdout
设置为'只读'套接字对象,所以无法设置该属性,因此您将遇到文本输出问题。
你可以通过定义__getattr__
和__setattr__
方法来修复它,就像你使用其他方法一样,但它是一个完整的黑客,所以你最好用你的'包装器'解决方案。