Python alternative for Unix 'which' command?

Is There a Python Equivalent to the ‘which’ Command?

Is there a cross-platform way in Python to determine which file will be executed by subprocess.Popen(file) without actually executing it? In other words, is there a Python equivalent to the Unix which command?

I’ve worked with Python for years, and for anyone needing a Python alternative to the Unix which command, here’s a straightforward approach. Python 3.3 introduced shutil.which()—a built-in, easy-to-use solution that directly mimics the Unix command. It’s reliable and simple:

import shutil

file = 'python'
file_path = shutil.which(file)

if file_path:
    print(f"The executable for '{file}' is located at: {file_path}")
else:
    print(f"'{file}' not found.")

This works like a charm to locate the path of the executable. So if you’re ever wondering ‘which python’ executable you’re running, this is your go-to method.

@ian-partridge’s method is great, especially for Python 3.3+. But let me add something interesting here for those who like a bit more manual control. If you want to simulate the which functionality without relying on shutil, you can use os.environ and iterate through the system’s PATH. This gives you more insight into how it works under the hood. Here’s a snippet:

import os

def which(file):
    path_dirs = os.environ["PATH"].split(os.pathsep)
    for directory in path_dirs:
        executable = os.path.join(directory, file)
        if os.path.isfile(executable) and os.access(executable, os.X_OK):
            return executable
    return None

file = 'python'
file_path = which(file)

if file_path:
    print(f"The executable for '{file}' is located at: {file_path}")
else:
    print(f"'{file}' not found.")

This method works for any version of Python, so whether you’re troubleshooting or just exploring ‘which python’ is being used, it’s a versatile choice!

I like how @shashank_watak gave us the manual route—really useful for learning the internals! But let’s not forget the power of leveraging existing Unix tools when working on Unix-based systems. If you prefer to directly invoke the which command itself from Python, the subprocess module has you covered. Here’s how you can do it:

import subprocess

def which(file):
    try:
        result = subprocess.run(['which', file], capture_output=True, text=True, check=True)
        return result.stdout.strip()
    except subprocess.CalledProcessError:
        return None

file = 'python'
file_path = which(file)

if file_path:
    print(f"The executable for '{file}' is located at: {file_path}")
else:
    print(f"'{file}' not found.")

This approach essentially combines the best of both worlds—using the Pythonic way to call the native which command. If you ever find yourself asking ‘which python’ executable your system is picking up, this method is efficient and directly aligns with Unix practices.