[debug笔记] 从pkgutil错误到sudo的原理

关键词和摘要

关键词: linux; 权限; sudo; python; pkgutil
摘要:(from Qwen)
在尝试使用 sudo pip install 在服务器上安装包时,遇到了与 pkgutil 和 Python 版本相关的错误。此错误源于低版本的 pip 使用了已废弃的 pkgutil.ImpImporter。更新 pipsetuptools 通常可以解决问题。
但在使用 sudo 时,由于其默认使用 root 的环境而非当前激活的 Anaconda 环境,更新可能无效。为确保使用正确的 Python 版本,建议明确指定 Python 路径或通过 sudo -E 保持当前环境变量,尽管后者可能引入安全风险。此经历强调了理解 Linux 命令副作用、多用户环境下的权限权衡以及关注命令执行上下文的重要性。

debug 过程

背景:前几天服务器的存储快满了,师兄在服务器上挂载了一块硬盘/sda,然后我们通过符号链接,在各自user下建立了一个映射目录。但是师兄谨慎起见,对这块挂载盘,权限给的是755(即普通用户没有写入权限),而又给了我们这些普通用户 sudo 的权限。

我在做课题的时候,项目目录保存在 /sda 下。项目要用 conda 启动一个专用的项目环境,然后用 pip install 命令安装依赖。此时我发现必须使用 sudo 才能安装(写入要求)。
sudo pip install ...

但是很快出现了 pkgutil 报错:

ERROR: Exception: Traceback (most recent call last): 
File "/usr/lib/python3/dist-packages/pip/_internal/cli/base_command.py", line 165, in exc_logging_wrapper status = run_func(*args) ^^^^^^^^^^^^^^^ 
File "/usr/lib/python3/dist-packages/pip/_internal/cli/req_command.py", line 205, in wrapper return func(self, options, args) ^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/usr/lib/python3/dist-packages/pip/_internal/commands/install.py", line 285, in run session = self.get_default_session(options) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/pip/_internal/cli/req_command.py", line 75, in get_default_session self._session = self.enter_context(self._build_session(options)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/usr/lib/python3/dist-packages/pip/_internal/cli/req_command.py", line 89, in _build_session session = PipSession( ^^^^^^^^^^^ 
File "/usr/lib/python3/dist-packages/pip/_internal/network/session.py", line 282, in **init** self.headers["User-Agent"] = user_agent() ^^^^^^^^^^^^ 
File "/usr/lib/python3/dist-packages/pip/_internal/network/session.py", line 157, in user_agent setuptools_dist = get_default_environment().get_distribution("setuptools") ^^^^^^^^^^^^^^^^^^^^^^^^^ 
File "/usr/lib/python3/dist-packages/pip/_internal/metadata/**init**.py", line 24, in get_default_environment from .pkg_resources import Environment 
File "/usr/lib/python3/dist-packages/pip/_internal/metadata/pkg_resources.py", line 9, in <module> from pip._vendor import pkg_resources 
File "/usr/lib/python3/dist-packages/pip/_vendor/pkg_resources/**init**.py", line 2164, in <module> register_finder(pkgutil.ImpImporter, find_on_path) ^^^^^^^^^^^^^^^^^^^ 
AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. Did you mean: 'zipimporter'?

我一搜发现,这是个很经典的报错,原因来自于:

使用的 pip 版本较低,使用了在 python 中的废弃 API pkgutil.ImpImporter,它在 python 3.3 中就标记为 deprecated

解决办法是:

  1. python -m pip install --upgrade pip 用python来更新pip
  2. python -m pip install --upgrade setuptools 升级 setuptools

问题没有解决

然而,照做之后,我发现问题还是没解决。
这与我搜到的各个回答都不一样,那些回答在更新 pip/setuptools 后都搞定了。
在仔细回顾各个过程以后,我开始怀疑是因为 sudo 的原因。
关键证据在于报错提示:/usr/lib/python3/dist-packages/pip/...。我在bash里虽然执行过 conda activate...,但是这里的python不是来自.../miniconda...

然后,在询问通义千问以后,我发现确实如此。sudo默认会使用root用户的环境,这导致我的更新实际上没起作用。我不能更改root用户的pip版本。所以就需要在sudo时,指定python版本为自己指定的版本。

大模型你是我的神

我的问题:

sudo命令有哪些副作用?
比如这样一个场景,
我的系统默认设置了一个python 环境变量,版本为3.8;
我在bash 里执行了 anaconda activate python310;这个环境里python 版本是3.10。
而当我想在挂载盘/sda上执行python操作时,假如它涉及写入命令,那么我就必须要用sudo。否则权限不允许我写入。
而我使用了 sudo python… 以后,请问我调用的 python,是 系统默认的 python 3.8 还是 anaconda activate 的python 3.10?

回答:

  1. sudo 原理:
    当你在终端中使用sudo执行命令时,实际上是以超级用户(通常是root)的身份运行这个命令。这意味着sudo会创建一个新的子shell,并以root用户的环境变量和权限来运行指定的命令。因此,sudo并不会继承当前用户的环境变量,包括你在当前会话中激活的Anaconda环境。

  2. 解答:会使用 系统环境
    在你描述的场景中,当你使用sudo python ...时,将会调用系统默认的Python解释器,也就是在root用户的PATH环境变量中找到的第一个Python解释器,通常是Python 3.8,因为你提到这是系统的默认版本。

  3. 解决方案:
    如果你需要以root权限运行Python 3.10,你需要确保这个版本的Python在root用户的PATH中可用,或者在使用sudo时明确指定Python 3.10的完整路径。例如,如果你知道Python 3.10的具体位置,你可以这样执行:

sudo /path/to/python3.10 ...

或者,如果你想在使用sudo时也能使用Anaconda环境中的Python,你可以在sudo命令后面加上-E选项来保留环境变量,然后激活你的Anaconda环境:

sudo -E bash -c 'source activate python310; python ...'

但是,这种方法并不推荐常规使用,因为保留用户的环境变量可能会带来安全风险,特别是在处理敏感操作或系统配置时。通常情况下,更好的做法是在需要root权限时,直接使用系统默认的Python版本,或者事先为root用户设置好所需的环境,然后再使用sudo命令。

总结

  1. 一直以来自己对linux的很多命令,了解不够全面、对副作用不够明晰,产生这种问题感觉也是大概率事件。
  2. 多用户环境下的权限设置要在便捷和安全性间做tradeoff
  3. 关注命令副作用。无论是在编程、使用软件组件的哪个阶段。
  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值