Skip to content

Instantly share code, notes, and snippets.

@westurner
Created November 16, 2017 11:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westurner/80e81cd4bf9b79acb5989622f2621655 to your computer and use it in GitHub Desktop.
Save westurner/80e81cd4bf9b79acb5989622f2621655 to your computer and use it in GitHub Desktop.
find all python*.exe and pip*.exe binaries on os.environ['PATH']
#!/usr/bin/env python
"""
Something like this as e.g site.discover
(for use as ``python -m site.discover``)
could be helpful for explaining and diagnosing multiple pythons and pips
"""
import os
import re
from distutils.spawn import find_executable
from subprocess import check_output, STDOUT
import collections
def discover(path=None, printsite=False, uniques=True):
"""
Find all ``python*`` and ``pip*`` executables and their version strings
within ``os.environ['PATH']``
Kwargs:
path (str): os.pathsep-delimited path str
(defaults to ``os.environ['PATH']``)
printsite (bool): call ``<python> -m site``
with each found python binary
uniques (bool): print uniques according to ``os.realpath`` at the end
Returns:
None
"""
if path is None:
path = os.environ['PATH']
rgx = re.compile(r'(python|pip)\-?(\d?\.?\d?)$')
uniques = collections.OrderedDict()
for directory in path.split(os.pathsep):
paths = sorted(
((match.group(0), match.group(2)) for match in
(rgx.match(name) for name in os.listdir(directory))
if match),
key=lambda x: x[::-1],
reverse=True)
print(u'# %s' % directory)
for (name, ver) in paths:
pathjoined = os.path.join(directory, name)
binpath = find_executable(pathjoined, directory)
realpath = os.path.realpath(binpath)
if binpath is None:
continue
if os.path.exists(pathjoined):
if os.path.islink(pathjoined):
print((
u"%r is a symlink to %r, which doesn't exist"
% (pathjoined, binpath)))
# TODO: %r exists but isnt executable
verstring = check_output((binpath, '-V'),
stderr=STDOUT).rstrip()
uniques.setdefault(realpath, collections.OrderedDict()) \
.setdefault(binpath, verstring)
print(u'%-11r %-5r %r' % (name, ver, verstring))
if printsite and name.startswith('python'):
sitestring = check_output((binpath, '-m', 'site'))
lines = (u'> %s' % l for l in sitestring.splitlines())
for line in lines:
print(line)
# TODO: check_output((binpath, '-m', 'pip'))
# TODO: AND/OR (?) only print uniques at the end
if uniques:
print('### UNIQUES')
for path in uniques:
print('## %s' % path)
paths = uniques.get(path)
for otherpath in sorted(paths):
print(otherpath)
print('')
if __name__ == '__main__':
discover()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment