简体   繁体   English

Python IDLE脚本不显示子进程的输出,但cmd.exe可以

[英]Python IDLE script does not show output of subprocess but cmd.exe does

I'm using Python 2.7.6 and IDLE on Windows 7. 我在Windows 7上使用Python 2.7.6和IDLE。

I have 2 Python scripts: 我有2个Python脚本:

script.py: script.py:

import subprocess, os, sys

print("hello 1")

mypath = os.path.abspath(__file__)
mydir = os.path.dirname(mypath)
start = os.path.join(mydir, "script2.py")

subprocess.call([sys.executable, start, "param"])

print("bye 1")

and script2.py that is being called by the previous script: 和上一个脚本正在调用的script2.py:

import sys

print "hello 2"

print (sys.argv[1])

print "bye 2"

If I run script.py with cmd.exe shell I get the expected result: 如果我使用cmd.exe shell运行script.py,则会得到预期的结果:

C:\tests>python ./script.py
hello 1
hello 2
param
bye 2
bye 1

But if I open script.py with the IDLE editor and run it with F5 I get this result: 但是,如果我使用IDLE编辑器打开script.py并使用F5运行它,则会得到以下结果:

>>> ================================ RESTART ================================
>>> 
hello 1
bye 1
>>> 

Why is the sub script not writing to the IDLE Python shell? 为什么子脚本未写入IDLE Python Shell?

You're running the subprocess without providing any stdout or stderr. 您在运行子流程时未提供任何stdout或stderr。

When run in a terminal, the subprocess will inherit your stdout and stderr, so anything it prints will show up intermingled with your output. 在终端中运行时,子进程将继承您的stdout和stderr,因此它打印的所有内容都将与您的输出混合显示。

When run in IDLE, the subprocess will also inherit your stdout and stderr, but those don't go anywhere. 当在怠速运转时, 子将继承你的输出和错误,但那些没有去任何地方。 IDLE intercepts the Python-level wrappers sys.stdout and sys.stderr ,* so anything you print to them from within Python will end up in the GUI window, but anything that goes to real stdout or stderr—like the output of any subprocess you run that inherits your streams—just goes nowhere.** IDLE拦截Python级别的包装器sys.stdoutsys.stderr ,*,因此您在Python内部打印到它们的任何内容都将最终出现在GUI窗口中,但是任何传递给实际 stdout或stderr的内容(如您子进程的输出)继承您的流的运行-无处可走。**

The simplest fix is to capture the stdout and stderr from the subprocess and print them yourself. 最简单的解决方法是从子流程中捕获stdout和stderr并自己打印。 For example: 例如:

out = subprocess.check_output([sys.executable, start, "param"],
                              stderr=subprocess.STDOUT)
print out

* IDLE is more complicated than it looks. * IDLE比看起来更复杂。 It's actually running separate processes for the GUI window and for running your code, communicating over a socket. 实际上,它正在为GUI窗口和用于运行代码的独立进程运行,并通过套接字进行通信。 The sys.stdout (and likewise for the others) that IDLE provides for your script isn't a file object, it's a custom file-like object that redirects each write to the GUI process via remote procedure call over the socket. IDLE为您的脚本提供的sys.stdout (以及其他脚本也是如此)不是file对象,它是一个自定义的类file对象,它通过套接字上的远程过程调用将每次write重定向到GUI进程。

** Actually, if you launched IDLE from a terminal rather than by double-clicking its icon, the subprocess's output may end up there . **实际上,如果从终端启动IDLE而不是双击其图标,则子进程的输出可能会在那里结束。 I'm not sure how it works on Windows. 我不确定它在Windows上如何工作。 But at any rate, that isn't helpful to you. 但是无论如何,这对您没有帮助。

I verified that abamert's change works in 2.7, on Win7, with Idle started normally from the icon. 我验证了abamert的更改在Win7的2.7中可以正常工作,并且Idle通常从图标开始启动。 The slight glitch is that 'print out' inserts an extra blank line. 轻微的故障是“打印”插入了额外的空白行。 This is easily changed by making print a function with a future import and use of the end parameter. 通过使print具有将来的导入功能并使用end参数,可以轻松更改此设置。

from __future__ import print_function
...
print(out, end='')

With Python 3, there is an additional issue that 'out' is bytes instead of str, so that it prints as 使用Python 3时,还有一个额外的问题,即“输出”是字节而不是str,因此它输出为

b'hello 2\r\nparam\r\nbye 2\r\n'

Since your output is all ascii, this can be fixed by changing the print call to 由于您的输出均为ascii,因此可以通过将print调用更改为

print(out.decode(), end='')

The resulting program works identically in 2.7 and 3.x. 生成的程序在2.7和3.x中的工作方式相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM