9

I need to invoke make (build a makefile) in a directory different from the one I'm in, from inside a Python script. If I simply do:

build_ret = subprocess.Popen("../dir1/dir2/dir3/make",
                     shell = True, stdout = subprocess.PIPE)

I get the following: /bin/sh: ../dir1/dir2/dir3/make: No such file or directory

I've tried:

build_ret = subprocess.Popen("(cd ../dir1/dir2/dir3/; make)",
                     shell = True, stdout = subprocess.PIPE)

but the make command is ignored. I don't even get the "Nothing to build for" message.

I've also tried using "communicate" but without success. This is running on Red Hat Linux.

3 Answers 3

12

I'd go with @Philipp's solution of using cwd, but as a side note you could also use the -C option to make:

make -C ../dir1/dir2/dir3/make

-C dir, --directory=dir

Change to directory dir before reading the makefiles or doing anything else. If multiple -C options are specified, each is interpreted relative to the previous one: -C / -C etc is equivalent to -C /etc. This is typically used with recursive invocations of make.

Sign up to request clarification or add additional context in comments.

Comments

9

Use the cwd argument, and use the list form of Popen:

subprocess.Popen(["make"], stdout=subprocess.PIPE, cwd="../dir1/dir2/dir3")

Invoking the shell is almost never required and is likely to cause problems because of the additional complexity involved.

3 Comments

The python docs say the following: If cwd is not None, the child’s current directory will be changed to cwd before it is executed. Note that this directory is not considered when searching the executable, so you can’t specify the program’s path relative to cwd. So I'm not sure if that will work.
The make program should be in the search path, of course. I'm pretty sure that this works (unless I made some silly typo) because I'm using it all the time.
Of course, in this case this is correct. I got a bit confused.
0

Try to use the full path, you can get the location of the python script by calling

sys.argv[0]

to just get the path:

os.path.dirname(sys.argv[0])

You'll find quite some path manipulations in the os.path module

1 Comment

Be careful when just using os.path.dirname. It returns an empty string when given just a file name. Calling os.path.abspath(os.path.dirname(sys.argv[0])) will always get you the the full path.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.