Jupyter Notebook PySpark 内核引用主机站点包中降低的 pip 版本
Jupyter Notebook PySpark Kernel referencing lowered pip version from host machine site-packages
我正在使用 Jupyter Notebook,它由名为 EMR Studio 的 AWS 托管服务提供。我对这些笔记本如何工作的理解是,它们托管在我作为我的 EMR 集群的一部分提供的 EC2 实例上。特别是使用任务节点的 PySpark 内核。
当前,当我 运行 命令 sc.list_packages()
时,我看到 pip 的版本是 9.0.1,而如果我通过 SSH 连接到主节点并且 运行 pip list
我看到 pip 的版本是 20.2.2。由于 Notebook 中降低的 pip 版本,我在执行命令 sc.install_pypi_package()
时遇到问题 运行。
在笔记本单元中,如果我 运行 import pip
那么 pip
我看到模块位于
<module 'pip' from '/mnt1/yarn/usercache/<LIVY_IMPERSONATION_ROLE>/appcache/application_1652110228490_0001/container_1652110228490_0001_01_000001/tmp/1652113783466-0/lib/python3.7/site-packages/pip/__init__.py'>
我假设这很可能是在某种 virtualenv 中 运行ning 作为任务节点上的应用程序?我不确定这一点,如果有的话,我也没有具体的证据证明 virtualenv 是如何配置的。
如果我 运行 sc.uninstall_package('pip')
然后 sc.list_packages()
我看到 pip 的版本是 20.2.2,这是我最初想要开始的。模块路径和前面说的一样
如何在 virtualenv 中获取 pip 20.2.2 而不是 pip 9.0.1?
如果我导入像 numpy 这样的包,我会看到该模块位于与 pip 所在的不同位置。有什么原因吗?
<module 'numpy' from '/usr/local/lib64/python3.7/site-packages/numpy/__init__.py'>
至于 pip 9.0.1,我目前唯一能找到的参考资料是 /lib/python2.7/site-packages/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl
。在此之外的一个目录中,我看到一个名为 virtualenv-15.1.0-py2.7.egg-info
的文件,如果我 cat
该文件表明它升级到 pip 9.0.1。我试图删除 pip 9.0.1 wheel 文件并将其替换为 pip 20.2.2 wheel,这导致 PySpark 内核无法正确配置。还有一个 virtualenv.py
文件确实引用了 __version__ = "15.1.0"
.
我找到了在 PySpark 使用的 virtualenv 中更新 pip、setuptools 和 wheel 的解决方案。
我最初必须确定 pip 9 的来源。通过 SSH 连接到我的 EMR 主节点,我将目录更改为根 cd /
,然后 运行 命令 sudo find . -name "pip*"
递归搜索 pip 文件可能位于的位置。
在我的场景中有一个 pip 9 轮位于:
./usr/lib/python2.7/site-packages/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl
通过在 /usr/lib/python2.7/site-packages
中多搜索一下,有一个 virtualenv.py
被调用来创建 virtualenv,下面会做更多解释。
在 PySpark notebook 会话中使用 %%info
显示 virtualenv 是从此文件路径创建的(感谢 Parag):
'spark.pyspark.virtualenv.bin.path': '/usr/bin/virtualenv'
运行 cat /usr/bin/virtualenv
显示正在从以下命令调用 virtualenv:
#!/usr/bin/python
import virtualenv
virtualenv.main()
/usr/bin中python的这个版本是python2.7。在终端我 运行 按顺序执行以下命令:
/usr/bin/python
import virtualenv
virtualenv
这输出:
<module 'virtualenv' from '/usr/lib/python2.7/site-packages/virtualenv.py'>
我有时看到这里使用了 virtualenv.pyc 文件,它位于 /usr/lib/python2.7/site-packages/
,但我看到其他用户建议可以删除 .pyc
文件。
在 EMR 主节点上,我 运行 命令 /usr/bin/virtualenv
显示了一些可以使用的标志。首先我使用了 /usr/bin/virtualenv --verbose ./myVE
这表明 pip 9.0.1 被打包到我创建的 virtualenv 中。如果我 运行 /usr/bin/virtualenv --verbose --download ./myVE2
这会显示更新版本的 pip、setuptools 和 wheel 正在从 Artifactory(我们的私有 PyPi 镜像)下载到 virtualenv 中。我们使用 /etc/pip.conf
来设置 index-url 和可信主机,以便使用 Artifactory 而不是 PyPi。
在这一点上,似乎 EMR 集群的 virtualenv.py 文件默认不会从 Artifactory/PyPi 下载更新的 wheel,而是使用位于 /usr/lib/python2.7/site-packages/virtualenv_support/*.whl
[=45 的 wheel 文件=]
运行 cat /usr/lib/python2.7/site-packages/virtualenv.py
显示此版本的 virtualenv 是 15.1.0
非常过时(2016 版)。
进一步阅读virtualenv.py发现main()函数有如下代码块:
parser.add_option(
"--download",
dest="download",
action="store_true",
help="Download preinstalled packages from PyPI.",
)
我将我的 EMR 主机上的这个 virtualenv.py 文件与 PyPi (https://pypi.org/project/virtualenv/15.1.0/) 的 virtualenv==15.1.0
官方版本进行了比较。我下载了 tar.gz 文件并在我的本地机器上解压。解压后的文件夹中有一个virtualenv.py文件。使用官方 virtualenv.py 文件的 diff
的内容与 EMR 集群的 virtualenv.py 文件进行比较时,只有几行不相同。主要区别在于上面代码块中的 parser.add_option
在官方 virtualenv.py 文件中具有 default=True,
。 EMR集群的virtualenv.py文件没有这个。
parser.add_option(
"--download",
dest="download",
action="store_true",
default=True,
help="Download preinstalled packages from PyPI.",
)
我从这里所做的是复制 EMR 集群的 virtualenv.py 并更新代码行以设置 default=True,
。然后,我将这个更新后的 virtualenv.py 作为 EMR bootstrap 脚本的一部分,以便在所有节点类型 (master/core/task) 上更新此文件。
bootstrap 脚本执行以下操作:
sudo rm /usr/lib/python2.7/site-packages/virtualenv.pyc
sudo rm /usr/lib/python2.7/site-packages/virtualenv.py
sudo aws s3 cp <UPDATED_VIRTUALENV_S3_PATH> /usr/lib/python2.7/site-packages/
确保从 S3 复制的文件只是调用 virtualenv.py
,以防因文件名不一致而导致任何问题。
现在,当我启动 PySpark 内核时,spark.pyspark.virtualenv.bin.path
调用更新后的 virtualenv.py 文件,我能够确认 pip 的版本号更高(20+),这就是我一直在寻找实现。
我正在使用 Jupyter Notebook,它由名为 EMR Studio 的 AWS 托管服务提供。我对这些笔记本如何工作的理解是,它们托管在我作为我的 EMR 集群的一部分提供的 EC2 实例上。特别是使用任务节点的 PySpark 内核。
当前,当我 运行 命令 sc.list_packages()
时,我看到 pip 的版本是 9.0.1,而如果我通过 SSH 连接到主节点并且 运行 pip list
我看到 pip 的版本是 20.2.2。由于 Notebook 中降低的 pip 版本,我在执行命令 sc.install_pypi_package()
时遇到问题 运行。
在笔记本单元中,如果我 运行 import pip
那么 pip
我看到模块位于
<module 'pip' from '/mnt1/yarn/usercache/<LIVY_IMPERSONATION_ROLE>/appcache/application_1652110228490_0001/container_1652110228490_0001_01_000001/tmp/1652113783466-0/lib/python3.7/site-packages/pip/__init__.py'>
我假设这很可能是在某种 virtualenv 中 运行ning 作为任务节点上的应用程序?我不确定这一点,如果有的话,我也没有具体的证据证明 virtualenv 是如何配置的。
如果我 运行 sc.uninstall_package('pip')
然后 sc.list_packages()
我看到 pip 的版本是 20.2.2,这是我最初想要开始的。模块路径和前面说的一样
如何在 virtualenv 中获取 pip 20.2.2 而不是 pip 9.0.1?
如果我导入像 numpy 这样的包,我会看到该模块位于与 pip 所在的不同位置。有什么原因吗?
<module 'numpy' from '/usr/local/lib64/python3.7/site-packages/numpy/__init__.py'>
至于 pip 9.0.1,我目前唯一能找到的参考资料是 /lib/python2.7/site-packages/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl
。在此之外的一个目录中,我看到一个名为 virtualenv-15.1.0-py2.7.egg-info
的文件,如果我 cat
该文件表明它升级到 pip 9.0.1。我试图删除 pip 9.0.1 wheel 文件并将其替换为 pip 20.2.2 wheel,这导致 PySpark 内核无法正确配置。还有一个 virtualenv.py
文件确实引用了 __version__ = "15.1.0"
.
我找到了在 PySpark 使用的 virtualenv 中更新 pip、setuptools 和 wheel 的解决方案。
我最初必须确定 pip 9 的来源。通过 SSH 连接到我的 EMR 主节点,我将目录更改为根 cd /
,然后 运行 命令 sudo find . -name "pip*"
递归搜索 pip 文件可能位于的位置。
在我的场景中有一个 pip 9 轮位于:
./usr/lib/python2.7/site-packages/virtualenv_support/pip-9.0.1-py2.py3-none-any.whl
通过在 /usr/lib/python2.7/site-packages
中多搜索一下,有一个 virtualenv.py
被调用来创建 virtualenv,下面会做更多解释。
在 PySpark notebook 会话中使用 %%info
显示 virtualenv 是从此文件路径创建的(感谢 Parag):
'spark.pyspark.virtualenv.bin.path': '/usr/bin/virtualenv'
运行 cat /usr/bin/virtualenv
显示正在从以下命令调用 virtualenv:
#!/usr/bin/python
import virtualenv
virtualenv.main()
/usr/bin中python的这个版本是python2.7。在终端我 运行 按顺序执行以下命令:
/usr/bin/python
import virtualenv
virtualenv
这输出:
<module 'virtualenv' from '/usr/lib/python2.7/site-packages/virtualenv.py'>
我有时看到这里使用了 virtualenv.pyc 文件,它位于 /usr/lib/python2.7/site-packages/
,但我看到其他用户建议可以删除 .pyc
文件。
在 EMR 主节点上,我 运行 命令 /usr/bin/virtualenv
显示了一些可以使用的标志。首先我使用了 /usr/bin/virtualenv --verbose ./myVE
这表明 pip 9.0.1 被打包到我创建的 virtualenv 中。如果我 运行 /usr/bin/virtualenv --verbose --download ./myVE2
这会显示更新版本的 pip、setuptools 和 wheel 正在从 Artifactory(我们的私有 PyPi 镜像)下载到 virtualenv 中。我们使用 /etc/pip.conf
来设置 index-url 和可信主机,以便使用 Artifactory 而不是 PyPi。
在这一点上,似乎 EMR 集群的 virtualenv.py 文件默认不会从 Artifactory/PyPi 下载更新的 wheel,而是使用位于 /usr/lib/python2.7/site-packages/virtualenv_support/*.whl
[=45 的 wheel 文件=]
运行 cat /usr/lib/python2.7/site-packages/virtualenv.py
显示此版本的 virtualenv 是 15.1.0
非常过时(2016 版)。
进一步阅读virtualenv.py发现main()函数有如下代码块:
parser.add_option(
"--download",
dest="download",
action="store_true",
help="Download preinstalled packages from PyPI.",
)
我将我的 EMR 主机上的这个 virtualenv.py 文件与 PyPi (https://pypi.org/project/virtualenv/15.1.0/) 的 virtualenv==15.1.0
官方版本进行了比较。我下载了 tar.gz 文件并在我的本地机器上解压。解压后的文件夹中有一个virtualenv.py文件。使用官方 virtualenv.py 文件的 diff
的内容与 EMR 集群的 virtualenv.py 文件进行比较时,只有几行不相同。主要区别在于上面代码块中的 parser.add_option
在官方 virtualenv.py 文件中具有 default=True,
。 EMR集群的virtualenv.py文件没有这个。
parser.add_option(
"--download",
dest="download",
action="store_true",
default=True,
help="Download preinstalled packages from PyPI.",
)
我从这里所做的是复制 EMR 集群的 virtualenv.py 并更新代码行以设置 default=True,
。然后,我将这个更新后的 virtualenv.py 作为 EMR bootstrap 脚本的一部分,以便在所有节点类型 (master/core/task) 上更新此文件。
bootstrap 脚本执行以下操作:
sudo rm /usr/lib/python2.7/site-packages/virtualenv.pyc
sudo rm /usr/lib/python2.7/site-packages/virtualenv.py
sudo aws s3 cp <UPDATED_VIRTUALENV_S3_PATH> /usr/lib/python2.7/site-packages/
确保从 S3 复制的文件只是调用 virtualenv.py
,以防因文件名不一致而导致任何问题。
现在,当我启动 PySpark 内核时,spark.pyspark.virtualenv.bin.path
调用更新后的 virtualenv.py 文件,我能够确认 pip 的版本号更高(20+),这就是我一直在寻找实现。