我想在一個單線程腳本中有一個交互式控制檯,該腳本有多個TCP連接打開。這意味着我不能只有一個標準輸入阻塞線程。在單線程Python腳本中有一個控制檯
有沒有簡單的方法來做到這一點?或者我應該把控制檯放在它自己的線程中並完成它?
我想在一個單線程腳本中有一個交互式控制檯,該腳本有多個TCP連接打開。這意味着我不能只有一個標準輸入阻塞線程。在單線程Python腳本中有一個控制檯
有沒有簡單的方法來做到這一點?或者我應該把控制檯放在它自己的線程中並完成它?
單線程或多線程都可以,但是如果您選擇不使用線程,您將需要使用輪詢(例如,可以使用poll(2)來完成輪詢),並檢查是否控制檯和/或TCP連接已準備就緒。
是的,我得到了那部分。我一直在想方便的方式來以類似控制檯的方式讀取用戶的輸入,同時輸出內容。就像它已經在圖書館或開源應用程序中完成一樣,我可以看看它。 – Blixt 2010-11-22 00:42:10
可以繼承InteractiveConsole(從內建的「代碼」模塊)和 與轉發到基座 InteractiveConsole的推送()方法之前重定向標準輸出/標準錯誤 到StringIO的實例的包裝覆蓋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
但是,這完全是另外一個問題... :-)
香港專業教育學院最近很多參觀這個問題。什麼在你看來,你真的描述的是或多或少的一個網絡服務器。 那就是我一直在想的 – 2016-10-04 16:38:51