通过 Homebrew 安装时 IPython 不读取 PYTHONPATH

PYTHONPATH is not read by IPython when installed via Homebrew

我在干净的 macOS Catalina(虚拟机)上使用 Homebrew 安装了 IPython 和 Python 3。

$ brew install ipython

由于 ipython 包依赖于 python3 包,Homebrew 将 ipythonpython3 一起安装。

$ brew info ipython 
ipython: stable 7.13.0 (bottled), HEAD
Interactive computing in Python
https://ipython.org/
/usr/local/Cellar/ipython/7.13.0 (2,905 files, 21.8MB) *
  Poured from bottle on 2020-04-15 at 18:48:22
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/ipython.rb
==> Dependencies
Required: python ✔, zeromq ✔
==> Options
--HEAD
    Install HEAD version
==> Analytics
install: 11,543 (30 days), 33,591 (90 days), 98,995 (365 days)
install-on-request: 5,404 (30 days), 15,768 (90 days), 49,364 (365 days)
build-error: 0 (30 days)

我预计这两个命令都从我的 shell 环境中读取 PYTHONPATH,因为 ipython 在由 pip3 install ipython.[=26 安装时可以正常工作=]

然而,使用 Homebrew 安装的 ipythonpython3 具有不同的 sys.path 设置。

$ which ipython
/usr/local/bin/ipython
$ which python3
/usr/local/bin/python3
$ ipython 
Python 3.7.7 (default, Mar 10 2020, 15:43:33) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import sys; sys.path                                                                                            
Out[1]: 
['/usr/local/Cellar/ipython/7.13.0/libexec/bin',
 '',
 '/usr/local/Cellar/ipython/7.13.0/libexec/lib/python3.7/site-packages',
 '/usr/local/Cellar/ipython/7.13.0/libexec/vendor/lib/python3.7/site-packages',
 '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
 '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
 '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
 '/usr/local/lib/python3.7/site-packages',
 '/usr/local/Cellar/ipython/7.13.0/libexec/lib/python3.7/site-packages/IPython/extensions',
 '/Users/oxon/.ipython']

$ python3
Python 3.7.7 (default, Mar 10 2020, 15:43:33) 
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys; sys.path
['', '/Users/oxon/root-6.20.02/obj/lib', '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python37.zip', '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7', '/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload', '/usr/local/lib/python3.7/site-packages']

Q1。它们为什么不同?

Q2。这是预期的行为吗?

Q3。为什么 IPython 被 pip3 install ipython 安装时读取 PYTHONPATH

Q1。为什么它们(即 sys.path)不同?

sys.path 的填充方式通常是: 1) 当前工作目录,然后是 2) 在您的 PYTHONPATH 环境变量中列出的目录,然后是 3) 安装相关的默认路径,这些路径由 site 模块控制。 来自 https://docs.python.org/3/using/cmdline.html : PYTHONPATH: 增加模块文件的默认搜索路径。 另见,例如, https://leemendelowitz.github.io/blog/how-does-python-find-packages.html https://realpython.com/lessons/module-search-path/ https://docs.microsoft.com/en-us/visualstudio/python/search-paths?view=vs-2019

因此,每个 python 安装可能有自己的 sys.path。 另外,sys.path不需要等于PYTHONPATH

检查两个(或三个?)案例中的每一个案例以及值和 post 返回:

import os
print( 'PYTHONPATH = ', os.environ['PYTHONPATH'] )

比如我在Ubuntu20.04下有spyder3和python3.8。当在同一个 CLI 启动时,每个都有自己的 sys.path,两个 "derived" 来自同一个 PYTHONPATH

Q2。这是预期的行为吗?

是的。

Q3。为什么 IPython 被 pip3 install ipython 安装时读取 PYTHONPATH

请 post PYTHONPATH ($ echo $PYTHONPATH) 的值,然后再在 CLI 中执行任何 python。他们是否正在读取其值并不明显。

如果这有助于找到原因,请post返回。

ipython 的 Homebrew 配方中归结为 the following line

bin.env_script_all_files(libexec/"bin", :PYTHONPATH => ENV["PYTHONPATH"])

它创建 /usr/local/bin/ipython 脚本,将 PYTHONPATH 设置为 IPython 正常工作所需的固定值(因为它的模块在默认 Python 之外模块目录)在调用 ipython 可执行文件之前:

#!/bin/bash
PYTHONPATH="/usr/local/Cellar/ipython/7.14.0/libexec/lib/python3.8/site-packages:/usr/local/Cellar/ipython/7.14.0/libexec/vendor/lib/python3.8/site-packages" exec "/usr/local/Cellar/ipython/7.14.0/libexec/bin/ipython" "$@"

它只是覆盖了您设置的 PYTHONPATH 值。您可以将脚本修改为:

PYTHONPATH="$PYTHONPATH:/usr/local/Cellar/...

这将使它附加到您的 PYTHONPATH 而不是完全覆盖它,但是当更新或重新安装 Homebrew 包时,该文件将被覆盖。因此,建议在 IPython 启动目录 ~/.ipython/profile_default/startup 中放入一个脚本,比如 root.py 看起来像:

import sys
sys.path.append('/Users/oxon/root-6.20.02/obj/lib')

当你使用pip安装ipython时,它的模块进入默认的Python模块目录,无论是系统目录还是用户目录还是虚拟环境中的目录,并且没有必要为了 ipython 正常运行而弄乱 PYTHONPATH

我会说 Q2 的答案是它可能是一个错误,你可以在 GitHub 上提交 Homebrew 的问题,尽管我不会考虑到他们如何对待 the same issue with Jupyter.

,我屏住呼吸