【问题标题】:sudo privileges within python virtualenvpython virtualenv中的sudo权限
【发布时间】:2018-10-24 10:19:15
【问题描述】:

环境

  • Windows Subsystem for Linux 与 GPS 进行串行通信。

  • Adafruit GPS 连接到连接到COM10 的 Arduino Nano。在Windows Subsystem for Linux 中,这相当于/dev/ttyS10

  • 要求:pyserial

我编写了一个简单的脚本来从 GPS 模块读取信息:

import serial

def select_sentence():
""" This function sends serial data to the GPS module to display only GPGGA and GPRMC"""

def read_gps():
    ser = serial.Serial("/dev/ttyS10", 9600)
    while True:
         print(ser.readline().decode('utf-8'))

if __name__ == "__main__":
     select_sentence()
     read_gps()

在 virtualenv 中,我选择了Python3,当我执行它时,我得到了Permission Error 用于串行端口/ttyS10,所以我选择sudo chmod 666 /dev/ttyS10 来使用virtualenv 中的脚本。

但是,为了避免PermissionErrors,是否有上述chmod /dev/serial 的替代方法?

我知道,即使在 virtualenv 中使用 sudo 时,也不会考虑安装在 virtualenv 中的软件包,而是 sudo 会查找您的全局 pip 软件包。

【问题讨论】:

    标签: python python-3.x virtualenv


    【解决方案1】:

    当你激活一个 virtualenv(source venv/bin/activate 或类似的)时,它基本上只是告诉你的 shell:“嘿,当你搜索一个命令时,在你查看其他任何地方之前先查看 venv/bin”,通过更新 @ 987654324@ 环境变量。这样,当您运行类似python 的命令时,您的shell 会看到并运行venv/bin 中的python,而不是/usr/bin 或其他任何地方。该 Python 副本配置为在 venv/lib 而不是 /usr/lib 中查找包,因此您可以使用 virtualenv 中的包而不是全局安装的包。

    但是,当您使用sudo 运行程序时,它是ignores $PATH。为什么这样做?因为在 *nix 的历史时期,设置 sudo 是很常见的,这样用户只能使用它执行特定的命令,比如(比如)sudo iftop1,这样任何人都可以检查什么网络正在被使用,但仍然没有人可以运行sudo rm -rf /*。如果 sudo 尊重用户的$PATH,您可以将/bin/rm 复制到~/bin/iftop,将~/bin 添加到您的$PATH,然后运行sudo iftop - 但您实际上会以root 身份运行rm

    所以,sudo 默认忽略$PATH。但是您仍然可以通过为 sudo 提供程序的完整路径来执行特定程序,因此您可以通过运行sudo ./venv/bin/python 之类的东西以root 身份在您的virtualenv 中执行Python(假设您的virtualenv 被称为venv)。这将使你成为 root,同时仍然可以访问你的 virtualenv 中的包,比如 pyserial。

    1:我实际上不知道有什么命令可以这样设置,这是一个不好的例子,对不起。

    【讨论】:

      【解决方案2】:

      还要确保您创建了没有 sudo 命令的 virtualenv,因为这可能会导致以后在没有 sudo 的情况下使用虚拟 env 时出现权限问题。如果是这种情况,请运行以下命令:

      sudo chown -R your_username:your_username path/to/virtuaelenv/

      您可以为您的用户启用读取/dev/ttyS10 的权限并由该用户运行python 脚本。

      注意:您还想将 shebang 行添加到您的 python 脚本的顶部,其中包含位于您的环境中的 python 解释器的路径。这样你就可以在没有解释器的情况下调用它。

      #!/usr/bin/env python
      

      查看更多关于 SO 的答案:Should I put #! (shebang) in Python scripts, and what form should it take?

      【讨论】:

      • 您也可以只使用#!/usr/bin/env python 而不是#!/path/to/venv/bin python3,它将自动使用您的venv 配置使用的任何python(或python3),特别是安装在venv 中的那个。
      • @TimS。谢谢 !这完全有道理。
      【解决方案3】:

      在你的 linux 机器中添加别名:

      # ~/.bash_aliases
      
      alias spython='sudo $(printenv VIRTUAL_ENV)/bin/python3'
      

      注意:确保您已激活虚拟环境。

      使用 spython 命令运行 python 脚本 :)

      spython file.py
      

      【讨论】:

        【解决方案4】:

        这是我在 bash 上的解决方法。将其放入 PATH 上的可执行文件中(例如 vesudo):

        #!/bin/bash
        
        if [ -z "$VIRTUAL_ENV" ]; then
          echo "Error: Virtual environment not found" >&2
          exit 1
        fi
        
        _args=''
        for _a in "$@"; do
          _a="${_a//\\/\\\\}"
          _args="$_args \"${_a//\"/\\\"}\""
        done
        
        sudo bash <<_EOF
        source "$VIRTUAL_ENV/bin/activate"
        $_args
        _EOF
        

        逻辑很简单:转义输入参数,运行特权子shell,获取虚拟环境并将参数传递给子shell。

        示例用法:

        ~/tmp$ source .venv/bin/activate
        (.venv) ~/tmp$ which python
        /home/omer/tmp/.venv/bin/python
        (.venv) ~/tmp$ vesudo which python
        /home/omer/tmp/.venv/bin/python
        (.venv) ~/tmp$ which pip
        /home/omer/tmp/.venv/bin/pip
        (.venv) ~/tmp$ vesudo which pip
        /home/omer/tmp/.venv/bin/pip
        (.venv) ~/tmp$ vesudo python -c 'import sys; print(sys.argv)' it works 'with spaced arguments' as well
        ['-c', 'it', 'works', 'with spaced arguments', 'as', 'well']
        (.venv) ~/tmp$ vesudo echo '$HOME'
        /root
        

        为方便起见,我将此脚本放在repo 中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-12-11
          • 1970-01-01
          • 1970-01-01
          • 2019-09-03
          相关资源
          最近更新 更多