Cross-platform cross-python shutil.which functionality for finding executable programs in the system PATH.
npx @tessl/cli install tessl/pypi-whichcraft@0.6.0whichcraft provides cross-platform cross-python shutil.which functionality for finding executable programs in the system PATH. It serves as a compatibility shim that works across multiple Python versions (2.7, 3.6, 3.7+) and operating systems (Linux, macOS, Windows), addressing the gap where shutil.which was only available in Python 3.3+.
pip install whichcraftfrom whichcraft import whichModule import:
import whichcraft
# Access as whichcraft.which()from whichcraft import which
# Find a command in PATH
executable_path = which('python')
if executable_path:
print(f"Python found at: {executable_path}")
else:
print("Python not found in PATH")
# Search for common utilities
date_cmd = which('date') # '/bin/date' on Unix-like systems
git_cmd = which('git') # Path to git executable if installed
nonexistent = which('fake-cmd') # None if not found
# Custom search path
custom_path = which('python', path='/usr/local/bin:/usr/bin')
# Custom file access mode
executable = which('script.py', mode=os.F_OK | os.X_OK)Locates executable programs in the system PATH with cross-platform compatibility and Python version independence.
def which(cmd, mode=os.F_OK | os.X_OK, path=None):
"""
Given a command, mode, and a PATH string, return the path which
conforms to the given mode on the PATH, or None if there is no such
file.
Parameters:
- cmd (str): Command name to search for
- mode (int, optional): File access mode, defaults to os.F_OK | os.X_OK
- path (str, optional): Custom search path, defaults to os.environ.get("PATH")
Returns:
str or None: Full path to executable if found, None otherwise
Platform-specific behavior:
- Windows: Handles PATHEXT environment variable and current directory precedence
- Unix-like: Direct command search without extensions
"""Basic executable search:
from whichcraft import which
# Find Python interpreter
python_path = which('python')
if python_path:
print(f"Python executable: {python_path}")
# Find system utilities
date_path = which('date') # Unix/Linux/macOS
where_path = which('where') # WindowsCustom search path:
import os
from whichcraft import which
# Search in specific directories
custom_path = '/usr/local/bin:/opt/bin'
result = which('custom-tool', path=custom_path)
# Search in environment PATH plus additional directory
extended_path = os.environ.get('PATH') + os.pathsep + '/home/user/bin'
result = which('my-script', path=extended_path)Custom file access mode:
import os
from whichcraft import which
# Default mode: readable and executable
default_result = which('python')
# Custom mode: only check if file exists
exists_result = which('python', mode=os.F_OK)
# Custom mode: readable, writable, and executable
rwx_result = which('python', mode=os.F_OK | os.R_OK | os.W_OK | os.X_OK)# Module-level constants
__author__: str = "Daniel Roy Greenfeld"
__email__: str = "pydanny@gmail.com"
__version__: str = "0.6.1"The which function handles errors gracefully:
None instead of raising exceptionsNone for inaccessible directoriesos.access() to check permissions before returning pathsshutil.which is unavailable