subprocess.Popen - `cwd` is not honored - python

For whatever reason,
from subprocess import Popen, PIPE, STDOUT
handle = Popen('echo %CD%', shell=True, stdout=PIPE, stderr=STDOUT, stdin=PIPE, cwd=r'C:\test')
print 'STDOUT::',handle.stdout.readline().strip()
Gives me:
STDOUT:: C:\Documents and Settings\myusername\Desktop
Windows XP (for whatever reason)
Python 2.6.6
Does this perhaps have any similarities to how windows executes commands in row such as:
C:\> cd "C:\test\" && echo %CD%
C:\
Which, is wrong.

If you are just trying to change the current working directory, you could use:
os.chdir('c:\\test')
Note the double backslash as the backslash is a special character in Python that needs to be escaped.
Also, to check your current working directory, you can use:
os.getcwd()

Tested with Win7 and Python 2.6 and 2.7, works as expected (STDOUT:: C:\test).
So this seems to be related to WinXP.

Related

Permission issues with popen within py2app

I am using py2app to bundle a python script, that uses the anaconda python distribution.
Since py2app doesn't play well with terminal scripts that need user input, I have a Tkinter file that py2app's setup.py launches, which then further launches my .py script using popen.
Locally, this works fine:
import subprocess as sub
command = "~/anaconda/bin/python -u myscript.py " + str(groups_count)
process = sub.Popen(command, shell=True, stdout=sub.PIPE, stderr=sub.PIPE, bufsize=1, universal_newlines=True)
But when I want to distribute this, I need to replace hardcoded paths and run this using the distribution contained within
import subprocess as sub
command = sys.executable + " -u myscript.py " + str(groups_count)
process = sub.Popen(command, shell=True, stdout=sub.PIPE, stderr=sub.PIPE, bufsize=1, universal_newlines=True)
This results in an error:
/bin/sh: /Users/username/projectname/appname/dist/MyOSXapp.app/Contents/MacOS/python: Permission denied
If I look at libpython2.7.dylib within /MyOSXapp.app/Contents/Frameworks it doesn't seem to be executable, but is readable by everyone. This is all assembled by py2app.
I need to run popen on my anaconda python distributed within pyapp. How do I do this?
I worked around this by adding executable permission to the python file saved by py2app within the osx .app file.
$ chmod +x ./dist/MyOSXapp.app/Contents/MacOS/python
Additionally, a fix for this was also added in py2app via issue 228.

Python subprocess communication

I'm trying to run a python script that will open a command prompt(OSGeo4W.bat is a command prompt line). I can get it to open but now I would like to send the command prompt commands.
import subprocess
myProcess = subprocess.Popen(['C:\OSGeo4W64\OSGeo4W.bat'],shell = False) #opens command prompt
myProcess.communicate('gdal2tiles -p raster -z 0-1 new.jpg abc')
myProcess.wait()
print("my process has terminated")
I've also tried
subprocess.check_call('gdal2tiles -p raster -z 0-1 new.jpg abc', shell=False)
I keep getting errors that say "WindowsError: [Error 2] The system cannot find the file specified"
although, if I were to keep the command prompt that it opens and type in " 'gdal2tiles -p raster -z 0-1 new.jpg abc' " then it will work just as I wanted. Help would be great, thanks!
Try:
check_call('gdal2tiles -p raster -z 0-1 new.jpg abc', shell=True)
shell=True changes how the executable is searched on Windows.
Or if gdal2tiles works only in the environment created by OSGeo4W.bat:
shell = Popen(r'C:\OSGeo4W64\OSGeo4W.bat', stdin=subprocess.PIPE)
shell.communicate('gdal2tiles -p raster -z 0-1 new.jpg abc')
# you don't need shell.wait() here
Notice: r"" literal. It is necessary to avoid escaping the backslashes in the path.
For those of you that are still trying to figure this one out, this is what I found. The "stdin=subprocess.PIPE" method above works with some command line tool in OSGeo4W64 but not all. It works with gdal_translate but not pdal translate for example. Not sure why;(
My Solution:
OSGeo4Wenv = r'CALL "C:/OSGeo4W64/bin/o4w_env.bat" '
pdal_translate_String = r'c:/OSGeo4W64/bin/pdal translate c:\inputFile c:\outputFile radiusoutlier --filters.radiusoutlier.min_neighbors=2 --filters.radiusoutlier.radius=8.0 --filters.radiusoutlier.extract=true'
Cmd = str(OSGeo4Wenv)+' & '+str(pdal_translateCmd)
shell = subprocess.call(Cmd, stdout=None, shell=True)
What is going on?
1) Open shell and set up the OSGeo4W environment by calling "OSGeo4Wenv". This is normally called by the OSGeo4W.bat file. Without this, the command line programs don't know where to look for the libraries.
2) The pdal_translate command is then sent to the dos shell because in Windows, multiple commands can be separated by the "&" symbol. I use the .call method of python 2.7. It has the advantage that it waits for the end of the process. That is nice if you use the multiprocessing map.pool method to launch multiple processes at the same time.
Hope this help others!
Nicolas

Python - Executing shell command does not work on Linux

I like to run a shell command from Python on my Linux Mint system.
Specifically the command runs all Bleachbit cleaners and works perfectly
fine when run maually.
Yet, trying to run the same command via the subprocess.call module
always results in an exception raised.
I just can not see why it should not work.
The command does not require sudo rights, so not requiring
right not given.
I also have firefox/browsers closed when executing the python command.
Anybody, any suggestions how to fix this issue?
My code:
try:
subprocess.call('bleachbit -c firefox.*')
except:
print "Error."
subprocess module does not run the shell by default therefore the shell wildcards (globbing patterns) such as * are not expanded. You could use glob to expand it manually:
#!/usr/bin/env python
import glob
import subprocess
pattern = 'firefox.*'
files = glob.glob(pattern) or [pattern]
subprocess.check_call(["bleachbit", "-c"] + files)
If the command is more complex and you have full control about its content then you could use shell=True to run it in the shell:
subprocess.check_call("bleachbit -c firefox.*", shell=True)
When shell is False you need to pass a list of args:
import subprocess
try:
subprocess.call(["bleachbit", "-c","firefox.*"])
except:
print ("Error.")

Running git commands using subprocess.Popen in python

I am writing a small python script that needs to execute git commands from inside a given directory
The code is as follows:
import subprocess, os
pr = subprocess.Popen(['/usr/bin/git', 'status'],
cwd=os.path.dirname('/path/to/dir/'),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
(out, error) = pr.communicate()
print out
But it shows git usage as the output.
If the command doesn't involve git for eg. ['ls'] then it shows the correct output.
Is there anything I am missing ?
python version - 2.6.6
Thanks.
subprocess.Popen:
On Unix, with shell=True: […] If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself.
You don't want shell=True and also a list of arguments. Set shell=False.

Getting the entire output from subprocess.Popen

I'm getting a slightly weird result from calling subprocess.Popen that I suspect has a lot to do with me being brand-new to Python.
args = [ 'cscript', '%USERPROFILE%\\tools\\jslint.js','%USERPROFILE%\\tools\\jslint.js' ]
p = Popen(args, stdout=PIPE, shell=True).communicate()[0]
Results in output like the following (the trailing double \r\n is there in case it's important)
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.\r\n\r\n
If I run that command from an interactive Python shell it looks like this
>>> args = ['cscript', '%USERPROFILE%\\tools\\jslint.js', '%USERPROFILE%\\tools\jslint.js']
>>> p = subprocess.Popen(args, stdout=subprocess.PIPE, shell=True).communicate()[0]
Lint at line 5631 character 17: Unexpected /*member 'OpenTextFile'.
f = fso.OpenTextFile(WScript.Arguments(0), 1),
...
Lint at line 5649 character 17: Unexpected /*member 'Quit'.
WScript.Quit(1);
So there's all the output I really care about, but if I dump the value of the "p" variable I just set up...
>>> p
'Microsoft (R) Windows Script Host Version 5.8\r\nCopyright (C) Microsoft Corpor
ation. All rights reserved.\r\n\r\n'
>>>
Where'd all that data I want end up going? It definitely didn't end up in "p". Looks like it's going to stdout, but I didn't I explictly tell it not to do that?
I'm running this on Windows 7 x64 with Python 2.6.6
Is it going to stderr? Try redirecting:
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True).communicate()[0]
It's probably going to stderr, as SimonJ suggested.
Also, the docs say not to use shell=True in Windows for your case:
The executable argument specifies the
program to execute. It is very seldom
needed: Usually, the program to
execute is defined by the args
argument. If shell=True, the
executable argument specifies which
shell to use. On Unix, the default
shell is /bin/sh. On Windows, the
default shell is specified by the
COMSPEC environment variable. The only
reason you would need to specify
shell=True on Windows is where the
command you wish to execute is
actually built in to the shell, eg
dir, copy. You don’t need shell=True
to run a batch file, nor to run a
console-based executable.
Later: oh wait. Are you using the shell to get those environment variables expanded? Okay, I take it back: you do need the shell=True.

Categories

Resources