Python中低级stdin的重复重定向

2024-04-16 05:54:33 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我的情况:有一些旧的C++代码,我试图创建一个简单的Python包装器。此代码最初设计为从命令行驱动,并期望通过管道将输入文件发送到其中。为了尽量减少对代码的干扰,我将main函数转换为一个普通的extern“C”函数,并将其编译成一个共享库,我用Python加载该库并通过ctypes驱动。注意,我不想通过系统调用来驱动这段代码,因为它最终将在集群上运行并执行无数次。在

从这里,我需要控制较低级别的STDIN,以便设置输入文件,以便它可以通过C++代码中的各种“CIN”语句读取。在

从我目前所了解到的情况来看,理论上我可以通过使用os库重写stdin文件描述符来做到这一点。我编写了下面的示例,它似乎在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()

这样就产生了输出

^{pr2}$

(以及“hello”和“hello2”两个文件)。太好了!不幸的是,当我的C++库函数正在读取STDIN流时,它似乎不起作用。第二次,它看起来很奇怪,但第二次是空的。当我重定向stdout而不是stdin时,它似乎工作得很好。在

有什么特别的事情我需要做重置较低级别的stdin流为第二次通过?在

附加信息:在c++端,stdin的读取方式如下:

while (getline(cin,line)) {
        //    do stuff with line...

我也不太关心解决方案是否是“仅限Linux”。在

编辑:我正在运行python2.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”处理stdin似乎与这种stdin重定向方法完全兼容。嗯。当然,通过这个方法创建了一个新的“cat”进程,并且每次都会连接新的stdin,所以它与调用我的库函数并不完全相同。我将尝试创建一个最小的库函数来重现这个问题。。。在


Tags: 文件to代码hellostreamosstdinstdout
1条回答
网友
1楼 · 发布于 2024-04-16 05:54:33

啊哈!结果,这个问题很有帮助:cin.ignore() and cin.clear() in C++

这样看来,至少在C++中,当流到达EOF时,它将各种错误标志设置为真(http://www.cplusplus.com/reference/ios/ios/good/)。这将阻止在流上执行进一步的操作。当我的库代码是一个独立的可执行文件时,这种行为很好,因为程序只会尝试从cin读取一个文件一次。然而,当代码转换成库时,当我的循环再次调用库函数时,库函数仍然在处理相同的stdin流。流仍然设置了错误标志,因此第二次读取cin失败。在

为了解决这个问题,我补充道

std::cin.clear();

在尝试cin读取之前。这将重置流的错误标志,然后可以很好地读取。在

我不确定是否可以在Python端处理流标志的重置;这将是一个好消息。在

相关问题 更多 >