Python子进程将数据定向到标准输入

Posted

技术标签:

【中文标题】Python子进程将数据定向到标准输入【英文标题】:Python subprocess directing data to standard intput 【发布时间】:2013-05-10 00:54:06 【问题描述】:

我在 Windows 上有一个从标准输入读取字符的 C++ 程序。我想编写一个 Python 脚本来打开这个 C++ 程序,然后让脚本写入程序的标准输入。

我可以在 Python 中成功创建子进程并从标准输出中读取。但是,该程序无法通过 Python 脚本从标准输入中接收任何内容。该程序使用 ReadConsole() 从标准输入中读取,并且即使 GetStdHandle() 返回没有错误,它也会重复返回错误代码 6 (Invalid Handle)。

这是程序代码:

char buffer[GIDE_BUFFER_SIZE];
HANDLE hConsole_c = GetStdHandle(STD_INPUT_HANDLE);
DWORD chars_read = 0;

if(hConsole_c == INVALID_HANDLE_VALUE )
    
    gide_printf(LOG_ERR,"ERROR: INVALID_HANDLE_VALUE for stdout: %d.", GetLastError());
    fflush(stdout);
    keyboard_handler_running = false;
    main_thread_running = false;
    
else if( hConsole_c == NULL)
    
    gide_printf(LOG_ERR,"ERROR: Unable to get handle to standard output.");
    fflush(stdout);
    keyboard_handler_running = false;
    main_thread_running = false;
    

gide_printf(LOG_DEBUG,"keyboard_listener thread started.");

Sleep(500); //sleep to give time for everything to come up.
print_menu();
memset(buffer, 0, sizeof(buffer));

//reads characters from console after enter is pressed.
//enter key adds CR and a LF so it adds two chars to all output.
while(keyboard_handler_running)
    
    if( ReadConsole( hConsole_c, buffer, sizeof(buffer), &chars_read, NULL ) == 0)
        
        gide_printf(LOG_ERR,"ERROR: Reading from console failed: %d.", GetLastError());
        ErrorHandler("blah");
        continue;
        
    gide_printf(LOG_DEBUG,"Read %d chars from console.", chars_read);
.
.
.
.

这是 Python 脚本:

import time
import subprocess
from subprocess import Popen, PIPE, STDOUT

print '0'
proc = subprocess.Popen('program.exe', stdout=None, stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
time.sleep(2)

print '1'
proc.stdin.write('xtyasmdmdjmdhjmdmjdmjd\n')
time.sleep(2)

print '2'
proc.stdin.close()
proc.stdout.close()
proc.kill()

MSDN 提到以下内容:虽然 ReadConsole 只能与控制台输入缓冲区句柄一起使用,但 ReadFile 可以与其他句柄(例如文件或管道)一起使用。如果与已重定向为控制台句柄以外的标准句柄一起使用,ReadConsole 将失败。 http://msdn.microsoft.com/en-us/library/windows/desktop/ms684958%28v=vs.85%29.aspx

我想知道这是否与它有关。

如果有人对如何执行此操作或使用 Python 的更好方法有任何建议,请告诉我。

谢谢。

【问题讨论】:

std::cin.read() 有什么问题? (可能有些问题 - 这些天我的 Windows 覆盖范围不完整/更喜欢 Linux)。 不。那不能解决它。 cin.getline(str,buffer_size) 将重复返回 0 个字符。所以它可能以类似的方式失败。它只是不太能说明为什么它会失败。 听起来流错误、不可读和/或 EOF 状态。无论如何,要确认问题出在 python 端还是 C++ 端,您可以检查您是否可以type input_file | your_app 并从非键盘管道正确读取它......如果可以,那么它就是 python。如果没有,std::string line; while (getline(std::cin, line)) ... 是对标准输入进行逐行解析的正常方式。 【参考方案1】:

我想出了一个解决方法,可以深入了解问题的本质。我正在使用 Windows 控制台项目在 Visual Studio 中工作。我创建了一个新的“空白项目”,而不是使用 ReadConsole() 的 Windows API,而是使用 std::cin.getline() 的 C++ API。这解决了问题。

再一次强调,这与其说是解决方法不如说是解决方法。但这表明问题似乎与 Windows API 或 Visual Studio 项目设置有关。

【讨论】:

以上是关于Python子进程将数据定向到标准输入的主要内容,如果未能解决你的问题,请参考以下文章

将子进程的标准输出重定向到 2 个或更多子进程的标准输入

使用重定向的标准输入处理子进程中的 kbhit

使用带有标准输入和标准输出重定向的 2 进程管道时如何避免标准输入上的重复输入

如何写入 Python 子进程的标准输入?

C - 将标准输入/输出重定向到单个双向文件描述符

如何将 gzip 输出重定向到 Popen 标准输入