Steve,

Great idea -- thanks!

Bryan

On Thu, Mar 16, 2017 at 12:51 PM, Steve Barnes <gadgetst...@live.co.uk>
wrote:

> I have also raised an issue on the cpython manuals,
> http://bugs.python.org/issue29829, requesting a note be added to the
> subprocess documentation.
>
> Steve
>
> On 16/03/2017 17:24, Coyot Linden (Glenn Glazer) wrote:
> > No, I hadn't seen that.
> >
> > Thanks for the pointer!
> >
> > Best,
> >
> > coyot
> >
> >
> > On 3/16/17 10:07, Jones, Bryan wrote:
> >> This link might be relevant
> >> -- https://github.com/pyinstaller/pyinstaller/wiki/Recipe-subprocess
> >>
> >> Have you tried those suggestions?
> >>
> >> On Thu, Mar 16, 2017 at 10:47 AM, Coyot Linden (Glenn Glazer)
> >> <co...@lindenlab.com <mailto:co...@lindenlab.com>> wrote:
> >>
> >>     We discovered that code which ran perfectly correctly by executing
> >>     the scripts in the POSIX environment or via python on the Windows
> >>     command prompt would fail when compiled using the -w flag to
> >>     PyInstaller. This flag prevents the application from launching a
> >>     console window when the application starts, which we clearly did
> >>     not want with our client. The problem occurs when a caller
> >>     executes Python's subprocess and the caller tries to implicitly or
> >>     explictly access stderr or stdin on Windows.
> >>
> >>     Because this originally occurred in our code with a caller of an
> >>     imported module our test code used that mode.  We believe it can
> >>     be reproduced without the caller.
> >>
> >>     We also believe that this error is a deep down result in the
> >>     pythonw implementation on Windows and PyInstaller just makes it
> >>     more obvious.  Some trials suggest that pythonw produces the same
> >>     failure cases, albeit with somewhat different output.
> >>
> >>     To the PyInstaller team: we found (and is reproducible with the
> >>     code in the appendices below) that even with -w, a console window
> >>     flashes for a tiny fraction of a second.  Is there any way to
> >>     eliminate that completely?
> >>
> >>     -----
> >>
> >>     So beginning with code that fails that shows the example, we have:
> >>
> >>     Sample problematic caller code:
> >>
> >>     #!/usr/bin/env python
> >>
> >>     import cgitb
> >>     import os.path
> >>     import subwrapper
> >>     import sys
> >>
> >>     cwd = os.path.dirname(os.path.realpath(str(sys.executable)))
> >>     cgitb.enable(logdir=cwd, format='text')
> >>
> >>     print subwrapper.getMachineID()
> >>
> >>     Sample problematic imported module code:
> >>
> >>     #!/usr/bin/env python
> >>
> >>     import subprocess
> >>
> >>     def getMachineID():
> >>        return subprocess.check_output(['wmic','csproduct','get','UUID'
> ])
> >>
> >>      Sample output under python:
> >>
> >>     >python caller.py
> >>     UUID
> >>     D8F59000-4F39-0000-0000-000000000000
> >>
> >>     Sample output when compiled with the -y --clean --onefile flags:
> >>
> >>     >caller.exe
> >>     UUID
> >>     D8F59000-4F39-0000-0000-000000000000
> >>
> >>     Sample output when compiled with the -y -w --clean --onefile flags:
> >>
> >>     No output.  Failure to execute script window appears (the name
> >>     depends on the script name):
> >>
> >>
> >>
> >>     Note that this error message is specific to PyInstaller, it comes
> >>     from
> >>     https://github.com/pyinstaller/pyinstaller/blob/
> a70b20e4de6a6817987d28ca9f3201c8105fd858/bootloader/src/pyi_launch.c#L411
> >>     <https://github.com/pyinstaller/pyinstaller/blob/
> a70b20e4de6a6817987d28ca9f3201c8105fd858/bootloader/src/pyi_launch.c#L411>
> >>     .
> >>
> >>     As noted above, we ran the toy scripts under cgitb tracing to
> >>     obtain detailed call stack information which does not normally
> >>     appear when that Window appears.  Full cgitb output is below, but
> >>     the important part is:
> >>
> >>     Traceback (most recent call last):
> >>       File "caller.py", line 11, in <module>
> >>       File "subwrapper.py", line 6, in getMachineID
> >>       File "subprocess.py", line 566, in check_output
> >>       File "subprocess.py", line 702, in __init__
> >>       File "subprocess.py", line 823, in _get_handles
> >>     WindowsError: [Error 6] The handle is invalid
> >>
> >>     Researching that error message led us to:
> >>
> >>     https://github.com/incuna/django-wkhtmltopdf/issues/91#
> issuecomment-179080434
> >>     <https://github.com/incuna/django-wkhtmltopdf/issues/91#
> issuecomment-179080434>
> >>
> >>     which points at the problem being related to the passing of
> >>     filehandles, but suggests hacking subprocess.py, which we were
> >>     extremely reluctant to do for production software.
> >>
> >>     We also found:
> >>
> >>     http://stackoverflow.com/questions/337870/python-
> subprocess-call-fails-when-using-pythonw-exe
> >>     <http://stackoverflow.com/questions/337870/python-
> subprocess-call-fails-when-using-pythonw-exe>
> >>
> >>     which states
> >>
> >>     /"sys.stdin and sys.stdout handles are invalid because pythonw
> >>     does not provide console support as it runs as a deamon, so
> >>     default arguments of subprocess.call() are failing.//
> >>     //
> >>     //Deamon (sic) programs close stdin/stdout/stderr purposedly and
> >>     use logging instead, so that you have to manage this yourself: I
> >>     would suggest to use subprocess.PIPE."/
> >>
> >>     The last comment at the end of that StackOverflow indicates that
> >>     people have been running into this problem with pythonw and
> >>     PyInstaller since 2014.
> >>
> >>     Putting these things together, we realized that -w is destroying
> >>     the stderr filehandle. We now do subprocess calls this way:
> >>
> >>         with open(os.path.join(cwd,'output'),'a') as bar:
> >>            with open(os.devnull) as nullin:
> >>                try:
> >>                    foo =
> >>     subprocess.check_output(['wmic','csproduct','get','UUID'],
> >>     stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=nullin)
> >>                    print >>bar, foo
> >>
> >>     which is to say that we never, ever use stdin or stderr on Windows
> >>     for anything, explicitly OR implicitly through default options.
> >>     E.g., passing None to check_output() for a handle or not
> >>     specifying a handle causes it to inherit from the parent and there
> >>     is nothing to inherit and hence the invalid handle error message.
> >>     No print statements, either.  All debugging must go to logs.
> >>
> >>     Best,
> >>
> >>     coyot
> >>
> >>     Appendix A - Correct Version of caller.py
> >>
> >>     #!/usr/bin/env python
> >>
> >>     import cgitb
> >>     import os.path
> >>     import subwrapper
> >>     import sys
> >>
> >>     cwd = os.path.dirname(os.path.realpath(str(sys.executable)))
> >>     cgitb.enable(logdir=cwd, format='text')
> >>
> >>     with open(os.path.join(cwd,'caller_output'),'a') as bar:
> >>         print >>bar, subwrapper.getMachineID()
> >>
> >>     Appendix B - Correct Version of subwrapper.py
> >>
> >>     Note that while this uses subprocess.PIPE for stderr, in practice
> >>     we use a file handle to the log file to capture any potentially
> >>     diagnostic output.
> >>
> >>     #!/usr/bin/env python
> >>
> >>     import cgitb
> >>     import os
> >>     import os.path
> >>     import subprocess
> >>     import sys
> >>
> >>     def getMachineID():
> >>        #return subprocess.check_output(['wmic','csproduct','get','UUID'
> ])
> >>        foo = ""
> >>        #note sys.executable works in the compiled environment.  If you
> >>     try this with
> >>        #pythonw caller.py, it will write its log files to wherever
> >>     python is and probably not
> >>        #what you want
> >>        cwd = os.path.dirname(os.path.realpath(str(sys.executable)))
> >>        cgitb.enable(logdir=cwd, format='text')
> >>        with open(os.path.join(cwd,'output'),'a') as bar:
> >>            with open(os.devnull) as nullin:
> >>                try:
> >>                    foo =
> >>     subprocess.check_output(['wmic','csproduct','get','UUID'],
> >>     stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=nullin)
> >>                except Exception, e:
> >>                     print >>bar, repr(e)
> >>        return foo
> >>
> >>     if __name__ == "__main__":
> >>         cwd = os.path.dirname(os.path.realpath(str(sys.executable)))
> >>         with open(os.path.join(cwd,'output'),'a') as bar:
> >>             print >>bar, getMachineID()
> >>
> >>     Appendix C - output from caller_output
> >>
> >>     >cat caller_output
> >>     UUID
> >>     D8F59000-4F39-0000-0000-000000000000
> >>
> >>     Appendix D - cgitb output
> >>
> >>     N.B., the code lives in a subdirectory of my cygwin homedir, but
> >>     everything was executed from the Windows command prompt.
> >>
> >>     <type 'exceptions.WindowsError'>
> >>     Python 2.7.11: c:\cygwin64\home\coyot\hg\stderrtoy\dist\caller.exe
> >>     Wed Mar 15 10:36:25 2017
> >>
> >>     A problem occurred in a Python script.  Here is the sequence of
> >>     function calls leading up to the error, in the order they occurred.
> >>
> >>      c:\cygwin64\home\coyot\hg\stderrtoy\dist\caller.py in <module>()
> >>
> >>
> >>      c:\cygwin64\home\coyot\hg\stderrtoy\dist\subwrapper.py in
> >>     getMachineID()
> >>
> >>
> >>      c:\cygwin64\home\coyot\hg\stderrtoy\dist\subprocess.py in
> >>     check_output(*popenargs=(['wmic', 'csproduct', 'get', 'UUID'],),
> >>     **kwargs={})
> >>
> >>
> >>      c:\cygwin64\home\coyot\hg\stderrtoy\dist\subprocess.py in
> >>     __init__(self=<subprocess.Popen object>, args=['wmic',
> >>     'csproduct', 'get', 'UUID'], bufsize=0, executable=None,
> >>     stdin=None, stdout=-1, stderr=None, preexec_fn=None,
> >>     close_fds=False, shell=False, cwd=None, env=None,
> >>     universal_newlines=False, startupinfo=None, creationflags=0)
> >>
> >>
> >>      c:\cygwin64\home\coyot\hg\stderrtoy\dist\subprocess.py in
> >>     _get_handles(self=<subprocess.Popen object>, stdin=None,
> >>     stdout=-1, stderr=None)
> >>
> >>     <type 'exceptions.WindowsError'>: [Error 6] The handle is invalid
> >>         __class__ = <type 'exceptions.WindowsError'>
> >>         __delattr__ = <method-wrapper '__delattr__' of
> >>     exceptions.WindowsError object>
> >>         __dict__ = {}
> >>         __doc__ = 'MS-Windows OS system call failed.'
> >>         __format__ = <built-in method __format__ of
> >>     exceptions.WindowsError object>
> >>         __getattribute__ = <method-wrapper '__getattribute__' of
> >>     exceptions.WindowsError object>
> >>         __getitem__ = <method-wrapper '__getitem__' of
> >>     exceptions.WindowsError object>
> >>         __getslice__ = <method-wrapper '__getslice__' of
> >>     exceptions.WindowsError object>
> >>         __hash__ = <method-wrapper '__hash__' of
> >>     exceptions.WindowsError object>
> >>         __init__ = <method-wrapper '__init__' of
> >>     exceptions.WindowsError object>
> >>         __new__ = <built-in method __new__ of type object>
> >>         __reduce__ = <built-in method __reduce__ of
> >>     exceptions.WindowsError object>
> >>         __reduce_ex__ = <built-in method __reduce_ex__ of
> >>     exceptions.WindowsError object>
> >>         __repr__ = <method-wrapper '__repr__' of
> >>     exceptions.WindowsError object>
> >>         __setattr__ = <method-wrapper '__setattr__' of
> >>     exceptions.WindowsError object>
> >>         __setstate__ = <built-in method __setstate__ of
> >>     exceptions.WindowsError object>
> >>         __sizeof__ = <built-in method __sizeof__ of
> >>     exceptions.WindowsError object>
> >>         __str__ = <method-wrapper '__str__' of exceptions.WindowsError
> >>     object>
> >>         __subclasshook__ = <built-in method __subclasshook__ of type
> >>     object>
> >>         __unicode__ = <built-in method __unicode__ of
> >>     exceptions.WindowsError object>
> >>         args = (6, 'The handle is invalid')
> >>         errno = 9
> >>         filename = None
> >>         message = ''
> >>         strerror = 'The handle is invalid'
> >>         winerror = 6
> >>
> >>     The above is a description of an error in a Python program.  Here is
> >>     the original traceback:
> >>
> >>     Traceback (most recent call last):
> >>       File "caller.py", line 11, in <module>
> >>       File "subwrapper.py", line 6, in getMachineID
> >>       File "subprocess.py", line 566, in check_output
> >>       File "subprocess.py", line 702, in __init__
> >>       File "subprocess.py", line 823, in _get_handles
> >>     WindowsError: [Error 6] The handle is invalid
> >>
> >>     --
> >>     You received this message because you are subscribed to the Google
> >>     Groups "PyInstaller" group.
> >>     To unsubscribe from this group and stop receiving emails from it,
> >>     send an email to pyinstaller+unsubscr...@googlegroups.com
> >>     <mailto:pyinstaller+unsubscr...@googlegroups.com>.
> >>     To post to this group, send email to pyinstaller@googlegroups.com
> >>     <mailto:pyinstaller@googlegroups.com>.
> >>     Visit this group at https://groups.google.com/group/pyinstaller
> >>     <https://groups.google.com/group/pyinstaller>.
> >>     For more options, visit https://groups.google.com/d/optout
> >>     <https://groups.google.com/d/optout>.
> >>
> >>
> >>
> >>
> >> --
> >> Bryan A. Jones, Ph.D.
> >> Associate Professor
> >> Department of Electrical and Computer Engineering
> >> 231 Simrall / PO Box 9571
> >> Mississippi State University
> >> Mississippi state, MS 39762
> >> http://www.ece.msstate.edu/~bjones <http://www.ece.msstate.edu/%
> 7Ebjones>
> >> bjones AT ece DOT msstate DOT edu
> >> voice 662-325-3149
> >> fax 662-325-2298
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "PyInstaller" group.
> > To unsubscribe from this group and stop receiving emails from it, send
> > an email to pyinstaller+unsubscr...@googlegroups.com
> > <mailto:pyinstaller+unsubscr...@googlegroups.com>.
> > To post to this group, send email to pyinstaller@googlegroups.com
> > <mailto:pyinstaller@googlegroups.com>.
> > Visit this group at https://groups.google.com/group/pyinstaller.
> > For more options, visit https://groups.google.com/d/optout.
>
> --
> Steve (Gadget) Barnes
> Any opinions in this message are my personal opinions and do not reflect
> those of my employer.
>
> --
> You received this message because you are subscribed to the Google Groups
> "PyInstaller" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to pyinstaller+unsubscr...@googlegroups.com.
> To post to this group, send email to pyinstaller@googlegroups.com.
> Visit this group at https://groups.google.com/group/pyinstaller.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Bryan A. Jones, Ph.D.
Associate Professor
Department of Electrical and Computer Engineering
231 Simrall / PO Box 9571
Mississippi State University
Mississippi state, MS 39762
http://www.ece.msstate.edu/~bjones
bjones AT ece DOT msstate DOT edu
voice 662-325-3149
fax 662-325-2298

Our Master, Jesus Christ, is on his way. He'll show up right on
time, his arrival guaranteed by the Blessed and Undisputed Ruler,
High King, High God.
- 1 Tim. 6:14b-15 (The Message)

-- 
You received this message because you are subscribed to the Google Groups 
"PyInstaller" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to pyinstaller+unsubscr...@googlegroups.com.
To post to this group, send email to pyinstaller@googlegroups.com.
Visit this group at https://groups.google.com/group/pyinstaller.
For more options, visit https://groups.google.com/d/optout.

Reply via email to