I'm trying to call a process from python using subprocess.call as shown below:
from subprocess import call
exePath = 'C:\\Test\\EXE.exe'
inPath = 'C:\\Test\\IN.in'
outPath = 'C:\\Test\\OUT.out'
call([exePath, inPath, outPath])
This prints a few lines from EXE.exe followed by "The handle is invalid" -- but as a string, not as an error, which makes me think it might be a message from the EXE.exe:
Unzipping Solution...
0.0% The handle is invalid.
However when I open cmd.exe and paste in:
C:\Test\EXE.exe C:\Test\IN.in C:\Test\OUT.out
it works fine.
Can someone point me in the right direction?
Thanks!
I'm running Python 2.7 64-bit on Windows 7.
EDIT:
It looks now like a problem in PyDev where the console cannot handle the the stdout from the process overwriting lines. The code runs fine from IDLE. Still looking for a fix for PyDev...
I think you're having this issue because PyDev is not a real terminal (i.e.: in Python, os.isatty() will return False when run from PyDev).
If the exe really relies on having a terminal, currently there's not much that PyDev can do...
For now, you can make your call from Python as:
In windows:
popen = subprocess.Popen(['myexe', 'params'], creationflags=subprocess.CREATE_NEW_CONSOLE)
popen.wait()
In Linux (as the CREATE_NEW_CONSOLE is not available):
args = ['xterm', '-e'] + ['myexe', 'params']
popen = subprocess.Popen(args)
popen.wait()
so that it works regardless of who's calling it :)
I think Aptana Studio does have an actual terminal replacement, but there's no PyDev integration to launch things on it...
Related
I have a python script that prints some 5-digit numbers. I call this script through a Qprocess and read its output which I use later on.
On windows the script is packaged into an executable with py2exe and the executable is called.
When I ran either the executable, or the script from a terminal, the output is fine, but when I call the executable through the Qprocess, I get garbage.
The part of my script that prints is like this
print number
sys.stdout.flush()
I tried replacing print with sys.stoud.write(number) and also with sys.stoud.write(number + '\n') but with no success.
my py2exe script is :
setup(
console=['number.py'],
options = {
'py2exe' : {
'bundle_files': 1,
'compressed': True
}
},
zipfile = None
)
I also tried changing console=['number.py'] to windows=['number.py'],
also with no success.
I know of -u switch of python, but I need to have it as an executable and I'm also not sure if this will work after all.
I have searched both on SO and google but everyone suggests using sys.stdout.flush() which is not enough for my case.
When I checked the output using a logger, I could see that the size of the output was different with a range from 6 characters to 11 incremented by 1 and then again from 6 to 11 and so on.
I' using Python 2.7 and the Qt is 4.8, I tested on Windows 7 and 8. On Linux everything runs smoothly.
I've wasted almost a whole day on this, I would appreciate any help
I also tried using \r\n when using sys.stoud.write(), but this didn't work too.
Trying to get this to work, I replaced the call to the executable with the call to the python script using the -u switch <python -u myscript.py> and it seems to work fine and the size of the output is always 6.
Why is this ?
Looking at the options provided by py2exe, I saw that there is the unbuffered option which says that when True unbuffered stdout and stderr(which I thought is unbuffered by default) are used.
unbuffered: if true, use unbuffered binary stdout and stderr
I set 'unbuffered': True in setup.py and this didn't work either.
You might need to add os.fsync(sys.stdout.fileno()).
Reference: os.fsync(fd)
Force write of file with filedescriptor fd to disk. On Unix, this calls the native fsync() function; on Windows, the MS _commit() function.
If you’re starting with a Python file object f, first do f.flush(), and then do os.fsync(f.fileno()), to ensure that all internal buffers associated with f are written to disk.
I'm trying to automate driver installation using a python script, previously i was using a batch file for the same task, since i'm now building a GUI using python i'd like to incorporate everything into python.
I was using pnputil.exe to install driver: 'pnputil -i -a path_to_inf'
but for some reason i can't make it work in python, i've tried subprocess.call, os.system, but nothing works, i always get some kind of error, using os.system i can run registry commands to read/write/add/remove keys, but with pnputil it just gives me errors.
os.system error = 'pnputil' is not recognized as an internal or external command,
operable program or batch file.
subprocess.call error = subprocess.Popen(['pnputil -i -a path_to_inf'], shell=True) = The filename, directory name or volume label syntax is incorrect.
You have to use the whole address of pnputil.exe to execute in python..
Try this
subprocess.Popen(['C:\\Windows\\System32\\PNPUTIL.exe -i -a path_to_inf'], shell=True)
Or
subprocess.Popen(['C:\\Windows\\SYSNATIVE\\PNPUTIL.exe -i -a path_to_inf'], shell=True)
Either should work, because it is based on 32-bit and 64-bit version
I ran across this issue myself and banged my head against it for quite a while. Putting this up here for anyone else that hits the issue as I wasn't able to find a good explanation of why this problem was occurring.
This problem happens because a 32-bit Python application is attempting to access a 64-bit Windows resource and is being automatically redirected to the incorrect path. More info on that relationship here:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
So, if your Python installation is 64-bit, you're already in the right context, and just a call to pnputil should work. If you're on 32-bit Python, you must redirect to sysnative. The following is the code I'm currently using to grab a list of driver store drivers:
import platform
import subprocess
if '32bit' in platform.architecture():
process = '%systemroot%\Sysnative\pnputil.exe -e'
else:
process = 'pnputil.exe -e'
p = subprocess.Popen(process, shell=True,
stdout=subprocess.PIPE, universal_newlines=True)
I have an application that launches a python script with parameters.
When the script runs i print some info on the cmd.
The funny thing is that i can't see anything from the print function on the cmd.
If i redirect sys.stdout to a file i get what i want to print which is strange.
I'm using python 2.6.4.
Anyone encountered something similar?
Are you using cmd.exe on windows? If so, there was or still is known problems trying to print to it using python. I believe the issue is a UTF-8 encoding problem. I have heard the following batch file will fix this issue (never tested).
set PYTHONIOENCODING=UTF-8
cmd /u /k chcp 65001
set PYTHONIOENCODING=
exit
Also its worth checking that your output is actually being flushed, try adding the following:
import sys
sys.stdout.flush()
i have a python script which should invoke a .exe file to get some result. That .exe file is invoking a new windows command prompt(shell) . i dont need any output from the .exe file.
i 'm using
os.system('segwin.exe args') in my script where segwin is an executable.
now my question is : i need to stop invoking cmd prompt
kudos to all
sag
Try this (untested):
import subprocess
CREATE_NO_WINDOW = 0x08000000
args = [...]
subprocess.check_call(["segwin.exe"] + args, creationflags=CREATE_NO_WINDOW)
Note that check_call checks the return code of the launched subprocess and raises an exception if it's nonzero. If you don't want that, use call instead.
In general, avoid os.system() and use the subprocess module whenever possible. os.system() always starts a shell, which is nonportable unnecessary on most cases.
This is actually specific to Windows. Windows has decided that segwin.exe is a console-based application (uses the Console subsystem from the Windows C interface).
I know how to invoke an prompt for apps that don't necessarily want one, but not the reverse, you could try using this, or this.
I've been using Cygwin on Windows recently. I want to use the Windows installation of Python, so during testing I'm using /cygdrive/c/Python26/python.exe myfile.py rather than python myfile.exe.
This is working almost perfectly, except for printing. When I run the Windows Python from Cygwin the output doesn't print until execution finishes. It works fine running in Windows Python from explorer.exe or cmd.exe, and it works in Cygwin using the Cygwin-installed Python (/bin/python.exe).
Is there a workaround for this? The important thing is to be able to run the Windows version, but I'd like to do it all from with Bash.
The real problem is that when you run a command in any of the Cygwin terminal programs like mintty, they don't act as Windows Consoles. Only Windows Console-based ones like CMD or Console2 do that. So, with Cygwin terminals the Windows python.exe doesn't think it is talking to an interactive console.
That leads to buffering output instead of flushing buffers on every line as is done in interactive sessions. That is why Amro's adding the flush() on every line fixes the symptom, but means changing the code.
One solution without changing the code is to turn off buffering in Python using the '-u' flag on the command line or setting the PYTHONUNBUFFERED environment variable.
export PYTHONUNBUFFERED=1
/cydrive/c/Python27/python.exe foo.py
or
/cydrive/c/Python27/python.exe -u foo.py
or run in interactive mode
/cydrive/c/Python27/python.exe -i foo.py
You will also not be able to run the Windows python.exe interactive mode in the Cygwin terminal. It will not bring up an interactive session, but will just hang. I find the best solution seems to be to use 'cygstart' (better than using the '-i' option):
cygstart /cygdrive/c/Python27/python.exe
And that seems to work with ipython as well (if installed):
cygstart /cygdrive/c/Python27/Scripts/ipython.exe
Not answering the initial question, but for those who want to use Python interactive session from within Cygwin terminal (for example in mintty) - start Python with "-i" option to tell it explicitly that it needs to run in interactive mode:
$ python -i
The neat way is also to create an alias in your .bashrc (knowing that it is only read for interactive terminal sessions anyway):
alias python='python -i'
Otherwise, Python will not know that it runs in the console, because all Cygwin pty-based terminals (mintty, rxvt and xterm) are recognized as pipes by Windows, not as the console. Therefore, Python thinks there is no console and enters non-interactive mode. So, if you still want interactive mode instead, you need to explicitly tell Python to use it. However, it still won't behave as it normally should - one still won't be able to use HOME or LEFT ARROW keys, and so on.
Perhaps if you flush the output
import sys
V = range(100000)
for x in V:
print x
sys.stdout.flush()