当stdout和stdin被重定向时,为什么Python没有按预期运行?

时间:2014-11-22 17:48:03

标签: 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");
}
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

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

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

  

解释器接口类似于UNIX shell,但提供了一些其他的调用方法:

     

当标准输入连接到tty设备调用时,它会提示输入命令并执行它们直到EOF(文件结束字符,您可以在UNIX上使用Ctrl-D生成它)或者按Ctrl-Z,在Windows上输入)。

     

使用文件名参数或文件作为标准输入调用时,它会从该文件中读取并执行脚本。

管道既不是文件也不是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.