【发布时间】:2013-11-15 11:43:06
【问题描述】:
这是我的情况:有一些旧的 C++ 代码,我正在尝试为其创建一个简单的 Python 包装器。此代码最初设计为从命令行驱动,并期望将输入文件通过管道传输到其中。为了尽量减少对这段代码的干扰,我将 main 函数转换为 vanilla extern "C" 函数并将其编译成一个共享库,我在 Python 中加载并通过 ctypes 驱动。请注意,我不想通过系统调用来驱动这段代码,因为它最终会在集群上运行并执行无数次。
从这里开始,我需要控制较低级别的标准输入以设置输入文件,以便可以通过 C++ 代码中的各种“cin”语句读取它。
从我目前所学的来看,理论上我可以通过使用 os 库覆盖标准输入文件描述符来做到这一点。我编写了以下示例,它似乎在 Python 中运行良好(基于此线程中的各种信息:Python version of freopen()):
import os
import sys
def freopen(f,option,stream):
oldf = open(f,option)
oldfd = oldf.fileno()
newfd = stream.fileno()
os.close(newfd)
os.dup2(oldfd, newfd)
# Original stdout file descriptor:
fd = sys.stdout.fileno()
orig_stream = os.fdopen(os.dup(fd), 'w')
# Test writing to file:
freopen("hello","w",sys.stdout)
print "world"
sys.stdout.flush()
freopen("hello2","w",sys.stdout)
print "world2"
sys.stdout.flush()
# Restore stdout to normal
os.dup2(orig_stream.fileno(),sys.stdout.fileno())
print "back to normal!"
# Test reading:
freopen("hello","r",sys.stdin)
print sys.stdin.readlines()
freopen("hello2","r",sys.stdin)
print sys.stdin.readlines()
这会产生输出
back to normal!
['world\n']
['world2\n']
(以及两个文件“hello”和“hello2”)对我来说。很好!不幸的是,当我的 C++ 库函数正在读取标准输入流时,它似乎不起作用。奇怪的是,它第一次工作得很好,但第二次却失败了;没有发生错误,看起来更像是 stdin 流对于第二次重定向只是空的。当我重定向标准输出而不是标准输入时,它似乎工作正常。
我需要做一些特殊的事情来为第二遍重置较低级别的标准输入流吗?
额外信息:在 c++ 端,stdin 的读取方式如下:
while (getline(cin,line)) {
// do stuff with line...
如果解决方案是“仅限 Linux”,我也不太担心。
编辑:我正在运行 Python 2.7.1
更新:嗯,也许库代码做了一些奇怪的事情,因为如果我将测试代码的“阅读测试”部分更改为:
# Test reading:
freopen("hello","r",sys.stdin)
os.system("cat")
freopen("hello2","r",sys.stdin)
os.system("cat")
然后是预期的输出
back to normal!
world
world2
仍在生产。因此,无论如何,'cat' 处理标准输入似乎与这种标准输入重定向方法完全兼容。唔。当然,通过此方法创建一个新的“cat”进程,并且每次都会连接新的标准输入,所以它与调用我的库函数并不完全相同。我将尝试创建一个重现问题的最小库函数...
【问题讨论】:
-
当您说它“第一次”有效时,您的确切意思是什么?只有第一行,第一次重启Python前,还是……?
-
啊抱歉。我的意思是我第一次执行重定向+运行库函数。整个库函数按预期执行。但是,如果稍后我重复该过程,将 stdin 重定向到一个新文件,如我的示例所示,则如果几行 python 行之后,库函数似乎没有从其 cin 调用中接收到任何输入并且失败。
-
基本上用调用库函数替换我的python示例中的“print sys.stdin.readlines()”来得到我的意思。
标签: c++ python io-redirection