subprocess seems not working in pyinstaller exe file
Question:
My program in tkinter
is working well when I am running it using PyCharm
,
when I am creating .exe
file using pyinstaller,
pyinstaller -i"icon.ico" -w -F script.py
I have no errors.
I am pasting script.exe
in same folder as my script.py
, and after running it I think in step where subprocess
is, it is not answering, because I haveprint
before subprocess line and its working.
Anyone know why?
This is the line with subprocess:
import subprocess
from subprocess import Popen, PIPE
s = subprocess.Popen([EXE,files,'command'],shell=True, stdout=subprocess.PIPE)
EDIT:
same problem with:
s = subprocess.check_output([EXE,files,'command'],shell=True, stderr=subprocess.STDOUT)
Answers:
Problem was solved by not using -w
command for generating exe file from .py script.
You can compile your code in -w mode or –windowed, but then you have to assign stdin and stderr as well.
So change:
s = subprocess.Popen([EXE,files,'command'],shell=True, stdout=subprocess.PIPE)
to:
s = subprocess.Popen([EXE,files,'command'],shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
Use this function to get the command’s output instead. Works with -F and -w option:
import subprocess
def popen(cmd: str) -> str:
"""For pyinstaller -w"""
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
process = subprocess.Popen(cmd,startupinfo=startupinfo, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
return decode_utf8_fixed(process.stdout.read())
I was getting the error
[WinError 6] The handle is invalid
when running the line
data = subprocess.check_output(['netsh', 'wlan', 'show', 'profiles']).decode('utf-8').split('n')
This solved it for me:
https://stackoverflow.com/a/43606682/12668094
After tinkering with some of the solutions from this and other threads, found another option, Windows-specific, but works with or without pyinstaller (windowed or console):
-
if you don’t care about capturing the output of the process and want to run it in a separate console window, allowing the user to interact with it, and wait until it finishes, you can do this:
import subprocess
def popen(cmd):
args = {'stdin' : subprocess.PIPE,
'stderr': subprocess.PIPE,
'stdout': subprocess.PIPE,
'env' : os.environ}
process = subprocess.Popen(['start','cmd','/C'] + cmd, close_fds=True, shell=True, **args)
return process
def run_subproc(args):
'''helper method to run a subprocess in a separate console window'''
p = popen(args)
output, err = p.communicate() # <- this is the key line to wait for process completion
status = p.wait() # <- doesn't actually wait if 'start' used
if __name__=='__main__':
run_subproc(['program.exe','arg1','arg2'])
My program in tkinter
is working well when I am running it using PyCharm
,
when I am creating .exe
file using pyinstaller,pyinstaller -i"icon.ico" -w -F script.py
I have no errors.
I am pasting script.exe
in same folder as my script.py
, and after running it I think in step where subprocess
is, it is not answering, because I haveprint
before subprocess line and its working.
Anyone know why?
This is the line with subprocess:
import subprocess
from subprocess import Popen, PIPE
s = subprocess.Popen([EXE,files,'command'],shell=True, stdout=subprocess.PIPE)
EDIT:
same problem with:
s = subprocess.check_output([EXE,files,'command'],shell=True, stderr=subprocess.STDOUT)
Problem was solved by not using -w
command for generating exe file from .py script.
You can compile your code in -w mode or –windowed, but then you have to assign stdin and stderr as well.
So change:
s = subprocess.Popen([EXE,files,'command'],shell=True, stdout=subprocess.PIPE)
to:
s = subprocess.Popen([EXE,files,'command'],shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
Use this function to get the command’s output instead. Works with -F and -w option:
import subprocess
def popen(cmd: str) -> str:
"""For pyinstaller -w"""
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
process = subprocess.Popen(cmd,startupinfo=startupinfo, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
return decode_utf8_fixed(process.stdout.read())
I was getting the error
[WinError 6] The handle is invalid
when running the line
data = subprocess.check_output(['netsh', 'wlan', 'show', 'profiles']).decode('utf-8').split('n')
This solved it for me:
https://stackoverflow.com/a/43606682/12668094
After tinkering with some of the solutions from this and other threads, found another option, Windows-specific, but works with or without pyinstaller (windowed or console):
-
if you don’t care about capturing the output of the process and want to run it in a separate console window, allowing the user to interact with it, and wait until it finishes, you can do this:
import subprocess def popen(cmd): args = {'stdin' : subprocess.PIPE, 'stderr': subprocess.PIPE, 'stdout': subprocess.PIPE, 'env' : os.environ} process = subprocess.Popen(['start','cmd','/C'] + cmd, close_fds=True, shell=True, **args) return process def run_subproc(args): '''helper method to run a subprocess in a separate console window''' p = popen(args) output, err = p.communicate() # <- this is the key line to wait for process completion status = p.wait() # <- doesn't actually wait if 'start' used if __name__=='__main__': run_subproc(['program.exe','arg1','arg2'])