Python history command has no output

93 views Asked by At

I'm trying to get the output of the history command in python, but it returns nothing. When I run it in the terminal it returns my last commands. I'm using Mac OS.

import subprocess

command = 'history'

# Execute the command using a shell
result = subprocess.run(command, shell=True, capture_output=True, text=True)

# Check the result
if result.returncode == 0:
    print("Command executed successfully!")
    print("Output:")
    print(result.stdout)
else:
    print("Error executing command:")
    print(result.stderr)

Output:

Command executed successfully!
Output:

4

There are 4 answers

0
Dowjones On BEST ANSWER

Here's a simple explanation of what I know about it:

When you run the history command via subprocess in Python, it typically returns nothing because history is not an actual command like ls or cat, but rather a shell builtin that's available in your terminal (like bash or zsh). This means history works within the context of a shell session to list the commands you've executed in that session, and it relies on the environment of the shell to function.

When you execute subprocess.run with shell=True, it starts a new shell session for that command, which doesn't have the same command history as your interactive terminal session. Therefore, the history command doesn't return anything because, from the perspective of that new shell session, no commands have been executed.

If you want to access the command history in a script, you might consider reading the history file directly. For bash, this is typically ~/.bash_history, and for zsh, it's ~/.zsh_history. You can read this file from Python to get the command history. Here's how you could do it for bash:

history_file = '~/.bash_history'

# Expand the path to the user's home directory
full_path = os.path.expanduser(history_file)

try:
    with open(full_path, 'r') as file:
        history = file.readlines()
    print("Command executed successfully!")
    print("Output:")
    for command in history:
        print(command.strip())
except Exception as e:
    print(f"Error reading history file: {e}")

Adjust the history_file variable if you're using a different shell. Thanks

2
OldBoy On

That is correct as there will not be any history. What you are doing in the Python program is starting a new shell to run whatever command(s) you pass to it. And in your case the very first command that that shell executes is history.

4
J_H On

history is a bash builtin, and is intended for interactive use.

You might prefer to directly open Path('~/.bash_history').expanduser() and read its contents.

0
Daniel Viglione On

In Mac OSX, I have two shells, bash and zsh. If you echo $SHELL in the terminal, you will find out the active shell. It will most likely produce an output like /bin/zsh. Note if you cd into /bin, you will also find /bin/bash. Therefore, to ensure you get the history of the active shell, you can use the following code. I just tested this and verified it produced the current active shell history in OSX:

import os

shell = os.environ["SHELL"]
print(shell)

shell_map = { "/bin/zsh" : ".zsh_history", "/bin/bash" : ".bash_history" }

for history in open(os.path.join(os.environ["HOME"], shell_map[shell])):
    print(history, end='')