【问题标题】:How to constantly send STDOUT to my python TCP server?如何不断将 STDOUT 发送到我的 python TCP 服务器?
【发布时间】:2011-04-30 21:16:06
【问题描述】:
  1. 我有一个简单的 python 回显服务器,它使用套接字,并将随机数回显给客户端。
  2. 我有另一个程序每 2 秒将值打印到标准输出。

如果它只是一个脚本,我可以像这样重定向'stdout' | python script.py ,并在像这样data = sys.stdin.read() 的脚本中获取它。但它是一个服务器,它不会像这样工作。

问题:如何编写这样一个 python 服务器,它可以监听/获取 Debian 上标准输出的值,并进一步传递它们。我不是要完整的代码。考虑到程序是服务器,只是关于获取标准输出的一些想法。

不断传入的值 > stdout > server.py > 进一步发送值

【问题讨论】:

  • 是在发送随机数的机器上打印值的另一个程序,还是在侦听发送的数字的机器上?
  • 现在 server.py 正在发送随机数,只是为了测试。但我需要 server.py 连续获取每 2 秒发送一次的标准输出值。我刚刚编写了另一个程序,例如生成值并通过标准输出将它们发送到服务器。
  • 您可以使用sys.stdin.read() 从标准输入读取数据,或者像使用任何其他文件句柄一样读取 .readlines() 等

标签: python stdout


【解决方案1】:

我认为你需要类似于Python subprocess 的东西。在该示例中,将dmesg 视为您的号码生成器,将grep 视为您的套接字服务器;但是,您只需在套接字服务器中打开一个PIPE,而不是生成一个 shell 命令。

假设您有两个进程,talker 和 server(在 Python 2.x 中)...

talker.py

​​>
"""
Call as talker.py <INTEGER_DELAY>
"""

import time
import sys

assert sys.version_info < (3, 0, 0)

DELAY = int(sys.argv[1])
ii = 1
while True:
    sys.stdout.write("Talk every %i seconds, blabbed %i times\n" % (DELAY, ii))
    sys.stdout.flush()
    ii += 1
    time.sleep(DELAY)

server.py

​​>
#!/usr/bin/env python

from subprocess import Popen, PIPE
from os import kill
import signal
import sys

assert sys.version_info < (3, 0, 0)

talkpipe = Popen(['python', 'talker.py', '3'],
    shell=False, stdout=PIPE)
try:
    while True:
        line = talkpipe.stdout.readline()
        print "SERVER HEARD", line.strip()
except KeyboardInterrupt:
    print "Killing child..."
    kill(talkpipe.pid, signal.SIGTERM)

使用./server.py 运行它会产生...

[mpenning@Bucksnort tmp]$ python server.py
SERVER HEARD Talk every 3 seconds, blabbed 1 times
SERVER HEARD Talk every 3 seconds, blabbed 2 times
SERVER HEARD Talk every 3 seconds, blabbed 3 times
SERVER HEARD Talk every 3 seconds, blabbed 4 times
^CTraceback (most recent call last):
  File "talker.py", line 11, in <module>
    time.sleep(DELAY)
KeyboardInterrupt
Killing child...
[mpenning@Bucksnort tmp]$

这些脚本的(更强大的)Python3 版本是...

talker.py

​​>

"""
talker.py: run talker.py with continuous stdout stream and control-C handling.

talker.py was written for Python3, but it should be fine under Python 2.X...
- To run under python 2.x, set `ENFORCE_PYTHON_3 = 0`

Execute with: 'python talker.py <DELAY_INTEGER>'
"""

import signal
import types
import time
import sys
import os

CATCH_CONTROL_C = 1
ENFORCE_PYTHON_3 = 1
BOUNDARY_CONDITIONS_SET = 0

def custom_signal_handler(signum, stackframe):
    assert isinstance(signum, int)
    assert isinstance(stackframe, types.FrameType)
    assert isinstance(BOUNDARY_CONDITIONS_SET, int) and BOUNDARY_CONDITIONS_SET >= 1

    print("---> custom_signal_handler() got signal: %s <---" % signum)
    if signum == 0:
        #  signal.SIG_DFL
        print(repr(stackframe))

    elif signum == 2:
        #  signal.SIGINT
        assert CATCH_CONTROL_C >= 1
        raise KeyboardInterrupt(repr(stackframe))

    else:
        raise NotImplementedError("Cannot handle signal %s" % signal.signum)

def set_boundary_conditions():

    global BOUNDARY_CONDITIONS_SET
    global DELAY_INTEGER

    assert isinstance(BOUNDARY_CONDITIONS_SET, int)
    assert BOUNDARY_CONDITIONS_SET <= 0

    if ENFORCE_PYTHON_3 == 1:
        assert tuple(sys.version_info) >= (3, 0, 0)

    # len(sys.argv) will be 1 if this script is imported into python
    # len(sys.argv) will be >= 2 if this script was called from CLI w/ args
    if len(sys.argv) == 1:
        # Called from an import statement...
        assert sys.argv[0] == ''
        DELAY_INTEGER = 1

    elif len(sys.argv) >= 2:
        # Called from the command-line... sys.argv[0] is the file name...
        assert sys.argv[0] == os.path.basename(__file__).strip()
        print("FOO", sys.argv[0])
        DELAY_INTEGER = int(sys.argv[1])
        assert DELAY_INTEGER > 0

    else:
        raise ValueError("DELAY_INTEGER was not specified correctly in the CLI")

    if CATCH_CONTROL_C >= 1:
        assert custom_signal_handler

        # Send control-C to the custom signal handler...
        signal.signal(signal.SIGINT, custom_signal_handler)
        print("    The current handler for signal.SIGINT is %s" % custom_signal_handler)

    else:
        assert signal.SIG_DFL
        # signal.SIGINT (control-C) is 2...
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        print("The current handler for signal.SIGINT is signal.SIG_DFL")

    BOUNDARY_CONDITIONS_SET = 1


def loop_talking_over_stdout():
    """
    Write messages to stdout with a variable delay...

    This function (loop_talking_over_stdout()) is a blocking call...
    """

    assert BOUNDARY_CONDITIONS_SET >= 1

    ii = 1
    while True:
        sys.stdout.write("Talk every %i seconds, blabbed %i times\n" % (
            DELAY_INTEGER, ii))
        sys.stdout.flush()
        ii += 1
        time.sleep(DELAY_INTEGER)

if __name__=="__main__":
    print("running python %s" % list(sys.version_info))
    set_boundary_conditions()
    loop_talking_over_stdout()

server.py

​​>
#!/usr/bin/env python3

from subprocess import Popen, PIPE
from os import kill
import signal
import shlex
import sys
import os

assert sys.version_info >= (3, 0, 0,)

def custom_signal_handler(signum, stackframe):
    assert isinstance(signum, int)

    print("Got signal: %s" % signum)
    raise KeyboardInterrupt(repr(stackframe))

# Send control-C to the custom signal handler...
signal.signal(signal.SIGINT, custom_signal_handler)

TIMEOUT = 3

while True:
    filepath = os.sep.join((os.getcwd(), 'talker.py'))
    cmd = 'python3 %s %s' % (filepath, TIMEOUT)
    talkpipe = Popen(shlex.split(cmd), shell=False,
        stdin=PIPE, stdout=PIPE, stderr=PIPE)

    stdout = talkpipe.stdout
    stderr = talkpipe.stderr
    stdin = talkpipe.stdin


    for line_out in iter(stdout.readline, b''):
        print(b'out>>> ' + line_out.rstrip())

        for line_err in iter(stderr.readline, b''):
            print(b'err-->' + line_err)

【讨论】:

  • 我有一个问题。我按照你建议的方式做了。我将显示上面的代码并且我得到了错误,我猜是因为当我尝试通过管道传递值时我的服务器已经在运行,并且它给出了我没有指定 args 或类似内容的错误。所以问题是:每次我通过管道传递值时,它都会将文件执行到它传递的值吗?
  • @Viktor,在不知道错误的情况下,描述不足以提供帮助在您的套接字服务器中。
  • @Mike 也许我只是弄乱了一些格式,因为它还发送 stderr 和 stdout ,它们是 None,None ,但我看到它对我的 args[0] 不满意,我必须这样做指定我何时运行 server ,为什么我断定它运行 server.py 并且不只是通过标准输入。文件“myslowpoetry.py”,第 36 行,在 parse_args 诗歌文件 = args[0] IndexError: list index out of range (None, None)
  • @Mike 是的。我刚刚检查过,错误正是因为它没有传递 args[0] ,这意味着每次我通过管道执行 send_random_number.py 时,它都会执行管道链接到的另一个文件,这对我的服务器来说是完全错误的,因为它需要运行,并且只需通过 PIPE 传递值。妈的....=)
  • @Viktor,您误解了我在文档中所指的内容...我发布了说明代码
猜你喜欢
  • 1970-01-01
  • 2021-08-28
  • 2017-02-25
  • 2021-09-05
  • 1970-01-01
  • 2013-03-27
  • 2023-03-23
  • 2019-01-21
  • 1970-01-01
相关资源
最近更新 更多