为什么不Python的表现时,标准输出和标准输入重定向预期? [英] Why doesn't Python behave as expected when stdout and stdin are redirected?

查看:193
本文介绍了为什么不Python的表现时,标准输出和标准输入重定向预期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在Windows重定向CMD.EXE标准输出和放大器;标准输入(带的CreateProcess())。只要我运行简单的命令或打开GUI应用它工作正常,但如果我尝试运行像蟒蛇软件,它并没有给我,这是输出了(也不获得通过标准输入输入)。

code例如:

\r
\r

的#include<&WINDOWS.H GT;\r
#包括LT&;&iostream的GT;\r
#包括LT&;串GT;\r
#包括LT&;螺纹>\r
\r
使用命名空间std;\r
\r
HANDLE child_input_read;\r
HANDLE child_input_write;\r
HANDLE child_output_read;\r
HANDLE child_output_write;\r
\r
无效writeToPipe()\r
{\r
而(真)\r
{\r
DWORD bytes_written;\r
string信息;\r
函数getline(CIN,味精);\r
味精+ ='\\ n';\r
BOOL成功= WriteFile的(child_input_write,msg.c_str(),msg.size(),放大器; bytes_written,NULL);\r
如果(!成功)\r
{\r
突破;\r
}\r
}\r
}\r
无效readFromPipe()\r
{\r
而(真)\r
{\r
DWORD bytes_read缓存;\r
字符缓冲区[512];\r
BOOL成功= ReadFile的(child_output_read,缓冲器,的sizeof(缓冲液)-1,&放大器; bytes_read缓存,NULL);\r
缓冲液[bytes_read缓存] = 0;\r
如果(!成功)\r
{\r
突破;\r
}\r
COUT<<缓冲;\r
}\r
}\r
无效createCmdProcess()\r
{\r
PROCESS_INFORMATION process_info;\r
STARTUPINFO startup_info;\r
SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES;\r
\r
为创建的管道句柄//设置安全属性\r
security_attributes.nLength = sizeof的(SECURITY_ATTRIBUTES);\r
security_attributes.bInheritHandle = TRUE;\r
security_attributes.lpSecurityDescriptor = NULL;\r
CreatePipe(安培; child_output_read,&放大器; child_output_write,&放大器; SECURITY_ATTRIBUTES,0);\r
CreatePipe(安培; child_input_read,&放大器; child_input_write,&放大器; SECURITY_ATTRIBUTES,0);\r
\r
//创建子进程\r
ZeroMemory(安培; process_info,sizeof的(PROCESS_INFORMATION));\r
ZeroMemory(安培; startup_info,sizeof的(STARTUPINFO));\r
startup_info.cb = sizeof的(STARTUPINFO);\r
startup_info.hStdInput = child_input_read;\r
startup_info.hStdOutput = child_output_write;\r
startup_info.hStdError = child_output_write;\r
startup_info.dwFlags | = STARTF_USESTDHANDLES;\r
的CreateProcess(NULL,cmd.exe的,NULL,NULL,TRUE,0,NULL,NULL,&放大器; startup_info,&放大器; process_info);\r
}\r
\r
诠释的main()\r
{\r
createCmdProcess();\r
线程t(writeToPipe);\r
线程T2(readFromPipe);\r
t.join();\r
t2.join();\r
系统(暂停);\r
}

\r

\r
\r


解决方案

这是不是一个错误,这是一个特点。 : - )

Python的设置和放大器;用法,第1.1.1节接口选项(强调):


  

该间preTER界面类似于UNIX的外壳,但提供调用的一些额外的方法:


  
  

在标准输入名为连接到一个tty设备,它提示输入命令并执行他们直到EOF(结束文件中的一个字符,可以产生与UNIX按Ctrl-D或按Ctrl-Z,Enter键在Windows上)被读取。


  
  

当一个文件名参数名为或以文件作为标准输入,它读取并从该文件执行脚本。


一个管既不是一个文件也不是tty设备,但它看起来像一个文件尽可能的C标准库(以及Python)的关注。因此第二行为踢和Python试图读取到文件的末尾。因为我们从来没有收我们的末端治理,这永远不会发生。

这行为不是在我看来,(或至少不能在Windows)特别懂事,如果你想,你可以提交一个bug。我猜想,这样的建议将被拒绝,因为任何变化将打破向后兼容性,但我可能是错的。

您可以解决该问题通过提供命令行 -i 选项:

 蟒蛇-i

这使得Python的进入互动模式,尽管标准输入不是终端

<一个href=\"http://stackoverflow.com/questions/11516258/what-is-the-equivalent-of-unbuffer-program-on-windows\">Unfortunately,没有已知的方法,使看起来像在Windows终端的管。

I try to redirect in windows the cmd.exe stdout&stdin (with CreateProcess()). It works fine as long as I run simple commands or open GUI apps, but if I try running a software like python, it does not give me it's output anymore (nor getting the input through stdin).

Code example:

#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");
}

解决方案

It's not a bug, it's a feature. :-)

From Python Setup & Usage, section 1.1.1, Interface options (emphasis added):

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.

A pipe is neither a file nor a tty device, but it looks like a file as far as the C standard library (and hence Python) is concerned. So the second behaviour kicks in, and Python attempts to read to the end of file. Since we never close our end of the pipe, that never happens.

This behaviour isn't particularly sensible in my opinion (or at least not in Windows) and you could file a bug if you wanted. I would guess that such a proposal would be rejected, since any change would break backwards compatibility, but I could be wrong.

You can work around the problem by providing the -i option on the command line:

python -i

That makes Python enter interactive mode, despite the fact that stdin isn't a terminal.

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

这篇关于为什么不Python的表现时,标准输出和标准输入重定向预期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆