Running a simple .py or .pyw python file causes python.exe
to show up under Task Manager.
python myApp.py
python myApp.pyw
However when we try to run it without using the console, the script does not appear to run, nor does python.exe
or pythonw.exe
appears under Task Manager
pythonw myApp.pyw
pythonw myApp.py
How do we troubleshoot the problem? The system is running Python 2.7.8 x64.
tl;dr
To troubleshoot, use output redirection on invocation:
pythonw myApp.py 1>stdout.txt 2>stderr.txt
This will capture stdout output, such as from print()
, in file stdout.txt
, and stderr output (such as from unhandled exceptions), in file stderr.txt
; from PowerShell, use
cmd /c pythonw myApp.py 1>stdout.txt 2>stderr.txt
).
Note that the very act of redirecting stdout may actually make your script work again, if the only reason for its failure with pythonw
was the use of print
(in Python 2.x - see below).
Caveat: This output redirection technique seemingly does not work when invoking *.pyw
scripts directly (as opposed to by passing the script file path to pythonw.exe
). Do let me know if you know why and/or if it does work for you.
Place the following at the top of any Python 2.x or 3.x script that you want to run with pythonw.exe
:
import sys, os
if sys.executable.endswith("pythonw.exe"):
sys.stdout = open(os.devnull, "w");
sys.stderr = open(os.path.join(os.getenv("TEMP"), "stderr-"+os.path.basename(sys.argv[0])), "w")
This ensures the following when a script is run with pythonw.exe
:
print()
calls and explicit calls to sys.stdout()
are effectively ignored (are no-ops).%TEMP%\stderr-<scriptFileName>
; %TEMP%
is a standard Windows environment variable that points to the current user's folder for temporary files.In other words: With the above code in place, check file %TEMP%\stderr-<scriptFileName>
after your script has failed silently when invoked with pythonw.exe
.
For an explanation, read on.
On Windows, pythonw.exe
is for launching GUI/no-UI-at-all scripts, which means that the
standard in- and output streams - sys.stdin
, sys.stdout
, sys.stderr
are NOT available.
This has two nasty side effects:
print()
- which targets sys.stdout
by default - causes an exception in Python 2.x.
print()
in 2.x - causes the script to abort silently.
sys.stderr
by default, which is the very thing not available in this scenario.The above code fixes these problems by:
sending stdout output to the null device, effectively ignoring any attempt to output to sys.stdout
- whether explicitly, or implicitly via print()
.
sending all stderr output to a temporary file.
Differences between Python 2.x and Python 3.x:
When a script is run with pythonw.exe
, sys.stdin
, sys.stdout
, and sys.stderr
:
sys.stdout
or sys.stderr
is the following exception: IOError: [Errno 9] Bad file descriptor
pythonw.exe
with -u
(for unbuffered output).print()
blindly tries to sys.stdout
(by default), so it provokes this exception sooner or later.None
print()
function performing a no-op (doing nothing) when it finds that sys.stdout
is None
, so that print()
statements can by default safely be used - they'll simply be ignored when run with pythonw.exe
sys.stdout.write()
and sys.stderr.write()
still results in an exception.See here for more background.