c++ - 为什么在重定向 stdout 和 stdin 时 Python 的行为不符合预期?

标签 c++ c windows redirect io-redirection

我尝试在 Windows 中重定向 cmd.exe stdout&stdin(使用 CreateProcess())。只要我运行简单的命令或打开 GUI 应用程序,它就可以正常工作,但如果我尝试运行像 python 这样的软件,它就不再给我它的输出(也不会通过标准输入获取输入)。

代码示例:

#include <windows.h> 
#include <iostream>
#include <string>
#include <thread>

using namespace std;

HANDLE child_input_read;
HANDLE child_input_write;
HANDLE child_output_read;
HANDLE child_output_write;

void writeToPipe()
{
	while (true)
	{
		DWORD bytes_written;
		string msg;
		getline(cin, msg);
		msg += '\n';
		BOOL success = WriteFile(child_input_write, msg.c_str(), msg.size(), &bytes_written, NULL);
		if (!success)
		{
			break;
		}
	}
}
void readFromPipe()
{
	while (true)
	{
		DWORD bytes_read;
		char buffer[512];
		BOOL success = ReadFile(child_output_read, buffer, sizeof(buffer)-1, &bytes_read, NULL);
		buffer[bytes_read] = 0;
		if (!success)
		{
			break;
		}
		cout << buffer;
	}
}
void createCmdProcess()
{
	PROCESS_INFORMATION process_info;
	STARTUPINFO startup_info;
	SECURITY_ATTRIBUTES security_attributes;

	// Set the security attributes for the pipe handles created 
	security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
	security_attributes.bInheritHandle = TRUE;
	security_attributes.lpSecurityDescriptor = NULL;
	CreatePipe(&child_output_read, &child_output_write, &security_attributes, 0);
	CreatePipe(&child_input_read, &child_input_write, &security_attributes, 0);

	// Create the child process
	ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));
	ZeroMemory(&startup_info, sizeof(STARTUPINFO));
	startup_info.cb = sizeof(STARTUPINFO);
	startup_info.hStdInput = child_input_read;
	startup_info.hStdOutput = child_output_write;
	startup_info.hStdError = child_output_write;
	startup_info.dwFlags |= STARTF_USESTDHANDLES;
	CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &startup_info, &process_info);
}

int main()
{
	createCmdProcess();
	thread t(writeToPipe);
	thread t2(readFromPipe);
	t.join();
	t2.join();
	system("pause");
}

最佳答案

这不是错误,这是一个功能。 :-)

来自 Python Setup & Usage, section 1.1.1, Interface options (强调):

The interpreter interface resembles that of the UNIX shell, but provides some additional methods of invocation:

When called with standard input connected to a tty device, it prompts for commands and executes them until an EOF (an end-of-file character, you can produce that with Ctrl-D on UNIX or Ctrl-Z, Enter on Windows) is read.

When called with a file name argument or with a file as standard input, it reads and executes a script from that file.

管道既不是文件也不是 tty 设备,但就 C 标准库(以及 Python)而言,它看起来像一个文件。所以第二个行为开始了,Python 尝试读取到文件末尾。由于我们从不关闭管道的末端,因此这种情况永远不会发生。

我认为这种行为不是特别明智(或者至少在 Windows 中不是),如果需要,您可以提交错误。我猜这样的提议会被拒绝,因为任何更改都会破坏向后兼容性,但我可能是错的。

您可以通过在命令行上提供 -i 选项来解决此问题:

python -i

这使得 Python 进入交互模式,尽管 stdin 不是终端。

Unfortunately, there is no known way to make a pipe that looks like a terminal on Windows.

关于c++ - 为什么在重定向 stdout 和 stdin 时 Python 的行为不符合预期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27080516/

相关文章:

c++ - WebViewProcessControl 初始化崩溃

c++ - 使用 CvPoints vector 时为 "no matching function for call to min_element"(opencv)

c - 找出出现次数超过 N/3 的数

c - atoi 的 Valgrind 错误

c - 在 C 中使用 bool 比较的问题

c++ - Windows 7中的进程和线程优先级

c# - 在 C# 中删除文本文件的第一行

c++ - 如何在控制台应用程序中使用仅消息窗口接收消息?

python - 从 python 启动 VS2008 构建

c++ - MFC 64 位代码在 Windows Server 2008 R2 上比 32 位慢