首页 > 编程问答 >在 Python Notebook 中调用 `subprocess` 具有与 `!` shell 不同的 `$PATH`

在 Python Notebook 中调用 `subprocess` 具有与 `!` shell 不同的 `$PATH`

时间:2024-07-25 10:41:28浏览次数:14  
标签:python shell subprocess ipython zsh

我正在 IPython 笔记本中交互地开发一个包装类。 这个包装类调用用 java 编写的命令行程序,因此我需要访问用于编译该程序的相同版本的 java 运行时。

但是,我注意到在笔记本中使用方便的 ! 运算符,生成的 shell 实例与在我的终端中使用 zsh 时不同。 这得到了确认:

!which java  # from within notebook cell
'/usr/bin/java' 

$ which java # on my zsh terminal
/opt/homebrew/opt/openjdk@11/bin/java 

运行 echo $PATH 也为每个路径产生了不同的路径。

然后我遇到了 这个 StackOverflow帖子,它解释了 ! 生成的子shell不会加载我的 .zshrc 文件(其中包含对在终端上使用 $PATH 时运行的 zsh 的修改)。 但是, ! 子shell 加载 .zshenv 文件(如果存在),我已成功将其创建为符号链接:

ln -s ~/.zshrc ~/.zshenv

运行此命令后, ! 现在有效地使用相同的|| |我在终端上使用的命令,并且命令按预期工作,并产生正确的结果: zsh !which java 但是 '/opt/homebrew/opt/openjdk@11/bin/java' ,我使用

作为测试和的便捷方法调试 shell 命令;但最终,我将这些 shell 命令调用移动到一个单独的 文件中,我在其中使用 ! 模块。 .py 当我使用 subprocess 从终端运行脚本时,一切都按预期工作;但是当从

导入函数到笔记本时,它会产生与以前相同的问题。 python3 script.py 作为一个最小的例子,从笔记本内部: script.py 这是正确的路径。 然而,

给了我:

!which java 
/opt/homebrew/opt/openjdk@11/bin/java 

为什么

import subprocess
process = subprocess.run("which java", shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = process.stdout.decode("utf-8").strip()
output

生成的shell能够访问我系统上与终端相同的

'/usr/bin/java'

,但 ! 生成的shell却无法访问? zsh on my system as the terminal, but the shell spawned by subprocess unable to?


你所觀察到的行為與 IPython 在子程序中設定環境變數的方式有關,特別是它處理 PATH 的方式。儘管連結 ~/.zshrc ~/.zshenv 會影響由 ! 使用的 shell,但它不會影響 subprocess 使用的環境。

以下是如何解決這個問題,並確保你的 Python 腳本使用正確 Java 版本的方法:

1. 明確設定 PATH 環境變數:

在你的 Python 腳本或筆記本儲存格中,明確地設定 PATH 環境變數,以包含你想要的 Java 可執行檔的路徑。你可以使用 os.environ 來執行此操作:

import os
import subprocess

# 取得目前的 PATH
current_path = os.environ['PATH']

# 將你想要的 Java 路徑新增到 PATH 的開頭
java_path = '/opt/homebrew/opt/openjdk@11/bin'
os.environ['PATH'] = f'{java_path}:{current_path}'

# 現在執行你的子程序
process = subprocess.run("which java", shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = process.stdout.decode("utf-8").strip()
print(output)  # 這應該會輸出 '/opt/homebrew/opt/openjdk@11/bin/java'

2. 直接使用 Java 可執行檔的完整路徑:

在你的 subprocess 呼叫中,不要依賴 PATH 來尋找 java ,而是提供可執行檔的完整路徑:

import subprocess

java_path = '/opt/homebrew/opt/openjdk@11/bin/java'
process = subprocess.run([java_path, '-version'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output = process.stdout.decode("utf-8").strip()
print(output)

這些方法可以讓你繞過從 PATH 中尋找 Java 可執行檔的問題,並確保你的腳本使用正確的版本。

請記住,在修改 PATH 環境變數時要小心,因為這可能會影響在你 Python 腳本中執行的其他程序。建議在修改後將其恢復為原始值,或使用更具體的方法,例如直接指定可執行檔的路徑。

标签:python,shell,subprocess,ipython,zsh
From: 78791234

相关文章

  • 在 VSCode 中激活 conda env 时,“which python”和“sys.path”给出不同的输出
    当我激活condaenv时,选择相应的解释器并在VScode中启动Python乍一看一切似乎都很好:(My_env)name@my_computer:~/Bureau/My_env/Code/current_dir$/home/name/anaconda3/envs/My_env/bin/python-mIPython--no-autoindentPython3.12.4|packagedb......
  • Python课程设计项目期末大作业(含免费源代码)
    选题代码下载地址:https://download.csdn.net/download/s44359487yad/89572689选题程序名称:口红色号识别器选题:基于图像处理、人脸识别和Flask构建的图片口红色号识别及商品推荐系统功能:根据上传的图片自动化图像处理后分析脸部特征,并判断其嘴部妆容状态,依托现......
  • python webbrowser.open 不使用默认浏览器
    对你们来说这是一个好奇的家伙..在我的python程序中webbrowser.open('etc..')打开MicrosoftEdge现在奇怪的是,我在与opensChrome(我的默认值)稍有不同的文件夹中还有另一个python程序关于发生了什么的任何想法吗?!!(我知道有人问过类似的问题,但......
  • 如何在 Mac 上运行 Python 文件来读取 txt 文件并将其写入外部硬盘?
    我目前有一个充满了我想阅读的epub的文件夹,一个我已经阅读过并想再次阅读的epub的文件夹,以及一个相应的文件,其中每个文件都有epub文件的名称。问题是,这些文件夹仅位于我的外部硬盘上。我想要做的是让我的脚本解析这些文件夹中的epub列表,并在我的下载文件夹中创建最新的副......
  • 深入探索:使用Python进行网站数据加载逻辑分析与请求
    作为一名资深的Python程序员,我经常需要从网站中提取数据以供分析或进一步处理。这项任务涉及到对网站数据加载逻辑的深入分析,以及使用Python进行高效的网络请求。在本文中,我将分享如何分析网站的数据加载方式,并使用Python的requests库来模拟浏览器行为,获取所需的数据。网站......
  • 如何将 Python 列表添加到 Excel 中已有值的列的末尾?
    我目前正在尝试编写一个程序,将值附加到列表中,然后将这些值添加到Excel数据表中的列中。每次运行该程序时,我都希望在同一列的末尾添加更多值。所以我不确定如何解决这个问题,而且我在网上找到的其他答案也没有取得多大成功。以下是使用openpyxl库在Python中将......
  • 如何学习Python:糙快猛的大数据之路(学习地图)
    在这个AI和大数据主宰的时代,Python无疑是最炙手可热的编程语言之一。无论你是想转行还是提升技能,学习Python都是一个明智之选。但是,该如何开始呢?今天,让我们聊聊"糙快猛"的Python学习之道。什么是"糙快猛"学习法?"糙快猛"学习法,顾名思义,就是:糙:不追求完美,允许存......
  • Python 中 __get__ 方法的内部原理
    我正在摆弄描述符,结果碰壁了。我以为我可以像使用任何其他方法一样直接调用它,但显然,它似乎不一致或者我遗漏了一些东西。假设我有一个用作描述符的坐标类:|||还有一个Point类,它有2个坐标属性:classCoordinate:def__set_name__(self,owner,name):self._na......
  • 使用带有私钥的云前端生成签名 URL 的问题..使用 Python 3.7 为带有空格的 S3 对象生
    我在使用Python3.7为S3对象生成签名URL时遇到问题。具体来说,键中带有空格的对象的URL会导致“访问被拒绝”错误,而没有空格的对象的URL通常工作正常。但是,并非所有不带空格的对象都能正常工作,带空格的对象始终会失败。fromdatetimeimportdatetime,timedeltaimpo......
  • 有没有更好的方法来在存储库中的一组 python 程序之间共享公共代码
    当我想要快速、轻松地做许多不同的事情时,我会选择Python-即我总是会得到许多Python“程序”-例如一组脚本-或者如果我正在玩一些东西,一堆测试程序等-即始终是许多不同程序的松散集合。但是,我会分享某些内容。例如,如果我正在使用AI-我可能有30个左右完全不相......