when I run the command /usr/bin/pydoc
, it prints
durd@FelixDu bin$ /usr/bin/pydoc
pydoc - the Python documentation tool
pydoc <name> ...
Show text documentation on something. <name> may be the name of a
Python keyword, topic, function, module, or package, or a dotted
reference to a class or function within a module or module in a
package. If <name> contains a '/', it is used as the path to a
Python source file to document. If name is 'keywords', 'topics',
or 'modules', a listing of these things is displayed.
pydoc -k <keyword>
Search for a keyword in the synopsis lines of all available modules.
pydoc -p <port>
Start an HTTP server on the given port on the local machine. Port
number 0 can be used to get an arbitrary unused port.
pydoc -g
Pop up a graphical interface for finding and serving documentation.
pydoc -w <name> ...
Write out the HTML documentation for a module to a file in the current
directory. If <name> contains a '/', it is treated as a filename; if
it names a directory, documentation is written for all the contents.
but I checked the code of /usr/bin/pydoc
, it shows
durd@FelixDu bin$ cat /usr/bin/pydoc
#!/usr/bin/python
import sys, os
import glob, re
partA = """\
python version %d.%d.%d can't run %s. Try the alternative(s):
"""
partB = """
Run "man python" for more information about multiple version support in
Mac OS X.
"""
sys.stderr.write(partA % (sys.version_info[:3] + (sys.argv[0],)))
dir, base = os.path.split(sys.argv[0])
specialcase = (base == 'python-config')
if specialcase:
pat = "python*-config"
else:
pat = base + '*'
g = glob.glob(os.path.join(dir, pat))
# match a single digit, dot and possibly multiple digits, because we might
# have 2to32.6, where the program is 2to3 and the version is 2.6.
vpat = re.compile("\d\.\d+")
n = 0
for i in g:
vers = vpat.search(i)
if vers is None:
continue
sys.stderr.write("%s (uses python %s)\n" % (i, i[vers.start():vers.end()]))
n = 1
if n == 0:
sys.stderr.write("(Error: no alternatives found)\n")
sys.stderr.write(partB)
sys.exit(1)
it should prints following text if it run /usr/bin/pydoc, but actually it is not.
python version 2.7.10 can't run ./pydoc. Try the alternative(s):
(Error: no alternatives found)
Run "man python" for more information about multiple version support in
Mac OS X.
then I checked the file in /usr/bin
durd@FelixDu Documents$ ls -al /usr/bin/pydoc*
-rwxr-xr-x 4 root wheel 925 Jul 16 2017 /usr/bin/pydoc
lrwxr-xr-x 1 root wheel 74 Sep 27 2017 /usr/bin/pydoc2.7 -> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/pydoc2.7
It seems when I run /usr/bin/pydoc
, it run /usr/bin/pydoc2.7
indeed, but I can't find there is some symbol link from /usr/bin/pydoc
to /usr/bin/pydoc2.7
, so I very confuse how does it works. Could anyone help to explain this?
thanks in advance.
The files aren't symlinks, because their contents aren't the same.
pydoc2.7
is a trivial entry-point script that uses /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
as its interpreter and just calls into that Python installation's pydoc.cli
.
pydoc
is a special Apple wrapper script that uses /usr/bin/python
. It isn't calling pydoc2.7
; it's indirectly calling a script buried inside the same framework that does the same thing.
/usr/bin/python
isn't actually a Python interpreter, it's a special tool that looks at your python-select
selection to decide which actual Python interpreter to run, and also handles special magic python-select
-aware scripts like this one.
These scripts are handy for things like 2to3
, which doesn't exist in Python 2.5. If you have 2.5 selected as your default Python, instead of a mysterious error, the script will tell you that you don't have 2to3
for Python 2.5, and suggest selecting 2.6 instead.
This also works for packages installed via easy_install
that use distribute
magic to create their entry-point scripts. For example, if you install such a package with 2.5, and then select 2.6 and try to run it, it'll tell you the problem and suggest either selecting 2.5 or installing the package for 2.6.
This is all very clever, and works pretty well. It would have worked a lot better if Apple had worked with third parties to let them plug other Python installations into the python-select
mechanism. Or if they'd kept up to date and make it work with Python 3, and with setuptools
/pip
instead of distribute
/easy_install
. And so on.
But since Apple no longer distributes anything but 2.7,1 and doesn't include the python-select
tool, and there are no cooperating distribute
libraries to install anymore, it's all just a bit of historic legacy lying around in a few scripts in /usr/bin
on every Mac.
1. Actually, they still have part of a Python 2.5 and 2.6 installation, and even a fragment of 2.3, which you can find by digging around inside the framework. But there's no python2.5
or python2.6
(or python2.3
) executable in there, just a copy of the python
shim that looks at your selection and ends up running 2.7.