我希望在单线程脚本中有一个交互式控制台,它有几个TCP连接打开。这意味着我不能只有一个阻止线程的标准输入。
有一种简单的方法吗?或者我应该把控制台放在自己的线程中并完成它?
答案 0 :(得分:3)
您可以继承InteractiveConsole(来自内置'代码'模块)和 使用重定向stdout / stderr的包装器覆盖push()方法 转发到基础之前到StringIO实例 InteractiveConsole的push()方法。你的包装器可以返回一个2元组 (更多,结果)其中“more”表示InteractiveConsole是否需要 更多输入,'result'是InteractiveConsole.push()写入的内容 你的StringIO实例。
听起来比实际更难。这是基本前提:
import sys
from cStringIO import StringIO
from code import InteractiveConsole
from contextlib import contextmanager
__all__ = ['Interpreter']
@contextmanager
def std_redirector(stdin=sys.stdin, stdout=sys.stdin, stderr=sys.stderr):
"""Temporarily redirect stdin/stdout/stderr"""
tmp_fds = stdin, stdout, stderr
orig_fds = sys.stdin, sys.stdout, sys.stderr
sys.stdin, sys.stdout, sys.stderr = tmp_fds
yield
sys.stdin, sys.stdout, sys.stderr = orig_fds
class Interpreter(InteractiveConsole):
"""Remote-friendly InteractiveConsole subclass
This class behaves just like InteractiveConsole, except that it
returns all output as a string rather than emitting to stdout/stderr
"""
banner = ("Python %s\n%s\n" % (sys.version, sys.platform) +
'Type "help", "copyright", "credits" or "license" '
'for more information.\n')
ps1 = getattr(sys, "ps1", ">>> ")
ps2 = getattr(sys, "ps2", "... ")
def __init__(self, locals=None):
InteractiveConsole.__init__(self, locals=locals)
self.output = StringIO()
self.output = StringIO()
def push(self, command):
"""Return the result of executing `command`
This function temporarily redirects stdout/stderr and then simply
forwards to the base class's push() method. It returns a 2-tuple
(more, result) where `more` is a boolean indicating whether the
interpreter expects more input [similar to the base class push()], and
`result` is the captured output (if any) from running `command`.
"""
self.output.reset()
self.output.truncate()
with std_redirector(stdout=self.output, stderr=self.output):
try:
more = InteractiveConsole.push(self, command)
result = self.output.getvalue()
except (SyntaxError, OverflowError):
pass
return more, result
查看这个完整的示例,它接受来自UDP套接字的输入:
启动两个控制台并在另一个中运行server.py,在另一个中运行client.py. 你在client.py中看到的内容应该与python无法区分 定期交互式解释器,即使所有命令都在 往返于server.py进行评估。
当然,使用这样的套接字是非常不安全的,但它 说明了如何异步评估外部输入。您 应该能够适应你的情况,只要你信任 输入源。当有人打字时,事情变得“有趣”:
while True: continue
但这完全是另一个问题......: - )
答案 1 :(得分:0)
单线程或多线程都可以,但如果您选择不使用线程,则需要使用轮询(例如,在C中这可以使用poll(2)完成)并检查是否控制台和/或TCP连接已准备就绪。