.pyw and pythonw does not run under Windows 7
Solution 1
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.
- To fix your script:
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 tosys.stdout()
are effectively ignored (are no-ops). - Stderr output, including from an unhandled fatal exception, is sent to file
%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:
-
Using
print()
- which targetssys.stdout
by default - causes an exception in Python 2.x.- This problem has been fixed in Python 3.x.
-
Any unhandled exception - including one triggered by
print()
in 2.x - causes the script to abort silently.- Exception error messages go to
sys.stderr
by default, which is the very thing not available in this scenario.
- Exception error messages go to
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 viaprint()
.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
:
- in Python 2.x: have invalid file descriptors
- The eventual result when trying to write to
sys.stdout
orsys.stderr
is the following exception:IOError: [Errno 9] Bad file descriptor
- Pitfall: Due to output buffering, this exception may not surface until you've output, say, 4K bytes; you can provoke it instantly by invoking
pythonw.exe
with-u
(for unbuffered output). -
print()
blindly tries tosys.stdout
(by default), so it provokes this exception sooner or later.
- The eventual result when trying to write to
- in Python 3.x: are set to
None
- This is complemented with the 3.x
print()
function performing a no-op (doing nothing) when it finds thatsys.stdout
isNone
, so thatprint()
statements can by default safely be used - they'll simply be ignored when run withpythonw.exe
- However, it follows that trying to use
sys.stdout.write()
andsys.stderr.write()
still results in an exception.
- This is complemented with the 3.x
See here for more background.
Solution 2
Try adding the line import sys; sys.stderr = open("errlog.txt", "w")
to the start of myApp.py
. Then look in errlog.txt
for a traceback or any other error messages.
Solution 3
I faced the same problem on a script of my own and found that when adding the output from Ross' answer the script would actually run.
It appears that for some reason that redirecting output fixes the problem. Since I'm not interested in writing the output to disk I've instead written it to /dev/null
(or the platform equivalent) with:
if ( sys.platform == 'win32' and sys.executable.split( '\\' )[-1] == 'pythonw.exe'):
sys.stdout = open(os.devnull, 'w')
sys.stderr = open(os.devnull, 'w')
The if statement ensures it only happens when the script is launched from pythonw.exe
. I'm not sure if it is related but it was important to do this before other imports (including e.g. import logging
).
Solution 4
I was having similar problem.
After debugging step by step by writing to a log file, I discovered that pythonw.exe crashed after a statement that tried to use the call: sys.stdout.write(). It turns out, when run with pythonw.exe, sys.stdout is None.
If you are using functions of sys.stdout/stderr/stdin, and intend to use your program with pythonw.exe, adding a check for "None" is a good idea.
Related videos on Youtube
Nyxynyx
Hello :) I have no formal education in programming :( And I need your help! :D These days its web development: Node.js Meteor.js Python PHP Laravel Javascript / jQuery d3.js MySQL PostgreSQL MongoDB PostGIS
Updated on June 19, 2022Comments
-
Nyxynyx almost 2 years
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
orpythonw.exe
appears under Task Managerpythonw myApp.pyw pythonw myApp.py
How do we troubleshoot the problem? The system is running Python 2.7.8 x64.
-
mklement0 almost 9 years@mfitzp: You need to redirect
sys.stderr
to a file as the first order of business, otherwise the error message from an unhandled exception is lost; see my answer.
-
-
mklement0 almost 9 yearsThe problem is not one of file associations; the problem is that scripts by default fail silently in the event of an unhandled exception when invoked with
pythonw.exe
rather thanpython.exe
. -
mklement0 almost 9 yearsYes, that fixes the problem, because, when a script is run with
pythonw.exe
,sys.stdin
,sys.stdout
, andsys.stderr
have either invalid file descriptors (2.x) , or areNone
(3.x). However, I suggest redirecting stderr to a an actual file, so that if your script dies due to an unhandled exception, you can at least find out why.