【问题标题】:Set up virtualenv with Paramiko SSH使用 Paramiko SSH 设置 virtualenv
【发布时间】:2023-12-20 13:24:01
【问题描述】:

我在 Windows 中使用 Python 和 Django 的经验有限,现在我正在尝试了解如何将我的代码部署到 Ubuntu 16.04 LTS VPS。在阅读了关于 SE 的各种教程和很多答案后,我设法进行了相当多的工作(嗯,对我来说),但现在我被卡住了。

手动(通过 Putty)我可以执行以下操作:

# check that Python 3.5 is installed
python3 --version  
# install pip
sudo -kS apt-get -y install python3-pip  
# upgrade pip to newest version
pip3 install --upgrade pip
# check result
pip3 --version  
# install venv
sudo -kS pip3 install virtualenv virtualenvwrapper 
# create venv
virtualenv ~/Env/firstsite  
# make sure venv is created 
ls -l ~/Env/firstsite/bin/python  # /home/droplet/Env/firstsite/bin/python3.5 -> python3
# switch on venv
source ~/Env/firstsite/bin/activate  # (firstsite) droplet@hostname:~$
# check that python3 is taken from venv
which python3  # /home/droplet/Env/firstsite/bin/python3

因此,虚拟环境已正确创建并打开。我可以继续安装 Django。

但是,当我尝试在自动化机制中执行完全相同的操作时,使用 Paramiko(我使用 paramiko.SSHClient().exec_command(cmd, input_string, get_pty=False 执行命令),一切都以完全相同的方式进行,直到最后一个命令:

exec_command('which python3')

返回/usr/bin/python3。所以我假设source activate 不能通过 Paramiko 的 SSH 工作。

  1. 为什么?
  2. 我该如何应对?
  3. 我能否检查是否以更直接(和可靠)的方式启用了 venv?

【问题讨论】:

    标签: python ubuntu ssh virtualenv paramiko


    【解决方案1】:

    取自@Pablo Navarro 在此处的回答:How to source virtualenv activate in a Bash script 帮助我解决了同样的问题(在 paramiko ssh 会话中激活环境)。

    在 exec_command 中给出环境中 python 可执行文件的路径,例如:

    stdin, stdout, stderr = ssh.exec_command(/path/to/env/bin/python script.py)
    

    就我而言(使用 miniconda 和一个名为 pyODBC 的环境):

    stdin, stdout, stderr = ssh.exec_command(~/miniconda2/envs/pyODBC/bin/python run_script.py)
    

    运行命令~/miniconda2/envs/pyODBC/bin/python -m pip list 打印此环境中的模块列表以确认

    【讨论】:

      【解决方案2】:

      我们可以轻松激活 virtualenv 并在其上执行命令。

      例子:

      import paramiko
      
      hostname = 'host'
      port = 22
      username = 'root'
      password = 'root'
      s = paramiko.SSHClient()
      s.load_system_host_keys()
      s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      s.connect(hostname, port, username, password)
      command = 'source /root/Envs/env/bin/activate;python3 --version;qark;echo hello'
      (stdin, stdout, stderr) = s.exec_command(command)
      for line in stdout.readlines():
          print(line)
      for line in stderr.readlines():
          print(line)
      s.close()
      

      【讨论】:

      • 我不同意“轻松激活”是可能的,因为仅仅在每个内部命令前加上source <venv_path>/bin/activate; <cmd> 的可能性并不容易。如果source ... 命令可以执行一次,然后通过 paramiko 的每个命令都将在虚拟环境中输入,那对我来说将是理想的。这似乎是不可能的。 :(