6276

How do I call an external command within Python as if I had typed it in a shell or command prompt?

0

66 Answers 66

1 2
3
2

I have written a wrapper to handle errors and redirecting output and other stuff.

import shlex
import psutil
import subprocess

def call_cmd(cmd, stdout=sys.stdout, quiet=False, shell=False, raise_exceptions=True, use_shlex=True, timeout=None):
    """Exec command by command line like 'ln -ls "/var/log"'
    """
    if not quiet:
        print("Run %s", str(cmd))
    if use_shlex and isinstance(cmd, (str, unicode)):
        cmd = shlex.split(cmd)
    if timeout is None:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, shell=shell)
        retcode = process.wait()
    else:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, shell=shell)
        p = psutil.Process(process.pid)
        finish, alive = psutil.wait_procs([p], timeout)
        if len(alive) > 0:
            ps = p.children()
            ps.insert(0, p)
            print('waiting for timeout again due to child process check')
            finish, alive = psutil.wait_procs(ps, 0)
        if len(alive) > 0:
            print('process {} will be killed'.format([p.pid for p in alive]))
            for p in alive:
                p.kill()
            if raise_exceptions:
                print('External program timeout at {} {}'.format(timeout, cmd))
                raise CalledProcessTimeout(1, cmd)
        retcode = process.wait()
    if retcode and raise_exceptions:
        print("External program failed %s", str(cmd))
        raise subprocess.CalledProcessError(retcode, cmd)

You can call it like this:

cmd = 'ln -ls "/var/log"'
stdout = 'out.txt'
call_cmd(cmd, stdout)
Sign up to request clarification or add additional context in comments.

Comments

2

Python 3.5+

import subprocess

p = subprocess.run(["ls", "-ltr"], capture_output=True)
print(p.stdout.decode(), p.stderr.decode())

Try online

Comments

2

Using the Python subprocess module to execute shell commands and write the output to a file.

The below script will run the ps -ef command, filter lines containing python3, and write them to a file called python_processes.txt. Note that the code does not handle any exceptions that might occur during execution.

import subprocess

# Command to execute
cmd = ["ps", "-ef"]

# Execute the command
process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output, error = process.communicate()

# Check if the command was executed without errors
if error is None:
    # Filter lines with 'python3'
    python_processes = [line for line in output.decode('utf-8').split('\n') if 'python3' in line]

    # Write the output to a file
    with open('python_processes.txt', 'w') as f:
        for process in python_processes:
            f.write(process + '\n')
else:
    print(f"Error occurred while executing command: {error}")


Comments

1

Sultan is a recent-ish package meant for this purpose. It provides some niceties around managing user privileges and adding helpful error messages.

from sultan.api import Sultan

with Sultan.load(sudo=True, hostname="myserver.com") as sultan:
  sultan.yum("install -y tree").run()

Comments

0

Here is a Python script that will run the command on Ubuntu, while also showing the logs in real-time:

command = 'your command here'    
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while True:
        output = process.stdout.readline().decode()
        if output == '' and process.poll() is not None:
            break
        if output:
            print(output.strip())
    rc = process.poll()
    if rc == 0:
        print("Command succeeded.")
       
    else:
        print("Command failed.")

Comments

-3

I use this for Python 3.6+:

import subprocess
def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : result, exit_code
    """
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()
    rc = process.wait()
    if rc != 0:
        print ("Error: failed to execute command: ", cmd)
        print (error.rstrip().decode("utf-8"))
    return result.rstrip().decode("utf-8"), serror.rstrip().decode("utf-8")
# def

1 Comment

Don't use set shell=True to run commands, it opens the program to command injection vulnerabilities. You're supposed to pass the command as a list with arguments cmd=["/bin/echo", "hello word"]. docs.python.org/3/library/…
1 2
3

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.