Python使用管道处理输入/输出
Posted
技术标签:
【中文标题】Python使用管道处理输入/输出【英文标题】:Python process input/output using pipes 【发布时间】:2019-02-15 00:24:56 【问题描述】:我正在编写一个 C++ 程序,它将 Python 3 解释器作为子进程运行,然后连接两个 Linux 匿名管道 - 一个连接到它的 stdout
和 stderr
,第二个连接到解释器的 stdin
;接下来通过这些渠道与之通信。
我需要在交互模式下运行 Python,即使用输入管道将一个命令传递给它并等待输出管道上的答案。一切都会好起来的,但似乎 Python 只有在 stdout
和 stdin
连接到 tty 时才能运行交互模式。
Python 文档引用:
解释器的操作有点像 Unix shell:当使用连接到 tty 设备的标准输入调用时,它以交互方式读取和执行命令;当使用文件名参数或文件作为标准输入调用时,它会从该文件读取并执行脚本。
确实,当我使用管道而不是 tty 运行解释器时,在发送命令后,我在响应管道中看不到任何内容。
那么 - 我可以通过某种方式解决这种行为并使 python3 解释器完全按照用户从终端启动的方式工作吗?
再次简述问题:
我需要将 Python 集成到我的 C++ 服务器应用程序中,以允许客户端执行 python 命令。 将解释器嵌入服务器看起来是个坏主意,主要是出于安全原因(用户可能会损坏服务器或其数据,此外服务器正在运行一些我不想授予用户的权限)。
另一种可能的解决方案是在 CLI 方式(命令模式)中使用解释器。主要问题是 - 然后我需要导入一些模块并预先执行一些代码以向用户提供我的服务器环境和一些 API。在每个命令都调用解释器之前做这件事太繁重了(这些操作非常复杂,包括建立网络连接)
因此,在单独的进程中运行解释器并使用 IPC 机制与其通信的服务器似乎不是一个坏主意。
无论如何,如果您有任何建议,我会很高兴看看您的建议。
【问题讨论】:
为什么需要 Python 交互运行?你不能只使用python -c
以非交互方式运行sn-p 吗?
@JohnKugelman 只需要预先导入一些 python 模块并为用户做一些事情。每次运行命令都会很重
我仍然不明白为什么你需要它是交互式的。请给我有关您尝试使用 Python 做什么的背景信息。我怀疑这是XY problem。
@JohnKugelman 我已经扩充了问题,请查看上下文
【参考方案1】:
您可以在 cli 方式中使用 python,每次运行用户输入的命令,或者将它们存档在文件中并按输入的行运行。通过这种方式,您可以更简单地使用它的输出。希望有用。
【讨论】:
不幸的是,在执行他的命令之前,我需要预先导入一些 python 模块并为用户做一些事情。每次运行命令都会很重【参考方案2】:如果您确实需要子进程认为它正在与终端通信,您可以使用伪终端或 pty 来实现。有两种不同的 API,一种来自 BSD Unix,另一种来自 System V,Linux 两者都支持。请参阅What do pty and tty mean? 或查看forkpty
或posix_openpt
的手册页。
但是,在这种情况下,我的猜测是 python 解释器正在块缓冲其输出。您可以通过使用 -u
调用它来禁用 stdin/stdout 上的缓冲来测试它。
【讨论】:
【参考方案3】:你正在做一些非常奇怪和不寻常的事情。交互式外壳旨在用于交互式使用,并带有人工输入命令。它不适用于输入来自另一个程序的交互式脚本。
话虽如此,是的,您可以这样做,尽管我真的不推荐它。您要做的是运行一个脚本,该脚本读取命令的标准输入,然后调用 exec() 方法。
一个简单的版本可能如下所示:
while True:
lines = []
while True:
line = input()
if line == "":
exec("\n".join(lines))
break
else:
lines.append(line)
上述程序在接收多行输入时的行为类似于 python shell,因为交互命令被缓冲并且直到有连续的空换行符才被执行。
对于脚本/编程使用,您可能需要一个比双换行符更健壮的块标记。例如,您可能希望使用空字符来中断命令块,以便可以安全地执行包含空行的脚本。
FWIW,我同意John Kugelman 的观点,无论如何这看起来都是个错误的问题。可能有比做这样的事情更好、更简单的方法来解决你的实际问题。你真正想做的是什么?
【讨论】:
我增加了问题,请看一下以上是关于Python使用管道处理输入/输出的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Python 将标准输入/标准输出通过管道传输到 Perl 脚本