1

I am new to the subprocess module in python.

The documentation provided this example:

>>> subprocess.check_output(["echo", "Hello World!"]) b'Hello World!\n' 

What I tried is:

>>> import subprocess >>> subprocess.check_output(["cd", "../tests", "ls"]) /usr/bin/cd: line 4: cd: ../tests: No such file or directory Traceback (most recent call last): File "<input>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output raise CalledProcessError(retcode, process.args, output=output) subprocess.CalledProcessError: Command '['cd', '../tests', 'ls']' returned non-zero exit status 1 

I am confused because this is my file structure:

 /proj /cron test_scheduler.py /tests printy.py test1.py test2.py ... 

These are my other attempts as well:

>>> subprocess.check_output(["cd", "../tests", "python", "printy.py"]) /usr/bin/cd: line 4: cd: ../tests: No such file or directory Traceback (most recent call last): File "<input>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output raise CalledProcessError(retcode, process.args, output=output) subprocess.CalledProcessError: Command '['cd', '../tests', 'python', 'printy.py']' returned non-zero exit status 1 >>> subprocess.check_output(["cd", "../tests;", "ls"]) /usr/bin/cd: line 4: cd: ../tests;: No such file or directory Traceback (most recent call last): File "<input>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output raise CalledProcessError(retcode, process.args, output=output) subprocess.CalledProcessError: Command '['cd', '../tests;', 'ls']' returned non-zero exit status 1 

4 Answers 4

3

Try to avoid shell=True if possible.

In this case, you can certainly avoid. The problem you are facing is: cd is a shell builtin. Its not a command/program/utility that can be called from outside. You need to be within a shell for cd to work. What you can instead do is change your current directory. Execute the command. And then go back to your original directory.

You'll need to do something like the below:

pathBefore = os.getcwd() os.chdir("/path/to/your/directory") subprocess.check_output(["ls"]) os.chdir(pathBefore) # get back to the path we were in before 

UPDATE: A better approach pointed out by @JFSebastian is to use the additional cwd argument to check_output call.

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

5 Comments

That is probably why I adopted to write Shell=True - as one of my first attempts was a cd. Now all pieces of the puzzle fall in place :)
If you are not doing anything with the shell, you are best away from using shell=True. It might seem like it makes life easy for you, but trust me, it might give you headaches in the long run.
True. My one time I used python was just when I needed some backup script while in a curious mood of trying some other language. So I have no deeper knowledge on best practices with python.
/usr/bin/cd (shown in the error message) is not a shell builtin. You should use cwd parameter instead of os.chdir().
@J.F.Sebastian Thanks! I agree, cwd argument is a better choice. I will edit my answer. BTW, great observation about /usr/bin/cd. It actually prompted me to read up a bit, and found out that cd is provided both as a shell builtin as well as a regular program.. Interesting.
1

The relative path to the tests directory depends on where the script is being run from. I would suggest calling subprocess.check_output(["pwd"]) to check where you are.

Also you can't combine two commands in the same call like in your attempt with ["cd", "../tests", "python", "printy.py"]. You'll need to make two separate calls with ["cd", "../tests"] and ["python", "printy.py"] respectively.

Comments

1

The error message is clear:

/usr/bin/cd: line 4: cd: ../tests: No such file or directory

that is you have successfully started /usr/bin/cd program that failed and printed the error message.

If you wanted to run ls command from ../tests directory instead:

import os import subprocess cwd = os.path.join(get_script_dir(), '../tests') output = subprocess.check_output(['ls'], cwd=cwd) 

where get_script_dir().

Note: do not use a relative path for the directory -- your script can be run from a different directory -- relative paths fail in this case.

Comments

0

You are missing a argument here I think.
Here a snippet from the only python script I ever wrote:

#!/usr/local/bin/python from subprocess import call ... call( "rm " + backupFolder + "*.bz2", shell=True ) 

Please note the shell=True in the end of that call.

1 Comment

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.