python子进程Popen环境路径?

2023-11-23

假设有一个可执行文件和一个用于启动它的 Python 脚本,并且它们位于“兄弟”子目录中,例如

/tmp/subdir1/myexecutable
/tmp/subdir2/myscript.py

If in /tmp和跑步python subdir2/myscript.py具有可执行文件的相对路径

# myscript.py
from subprocess import Popen
proc = Popen(["../subdir1/myexecutable"])

它使OSError: [Errno 2] No such file or directory.

Python如何搜索可执行文件?它是否使用脚本的当前工作目录和/或位置?它使用 PATH 和/或 PYTHONPATH 吗?你能改变地点和方式吗subprocess.Popen搜索可执行文件?命令、可执行文件的绝对路径和相对路径是否有不同的处理方式? Linux 和 Windows 之间有区别吗?什么是shell=True or shell=False影响?


相对路径(包含斜杠的路径)永远不会在任何路径中被检查PATH, 无论你做什么。它们是相对于当前工作目录仅有的。如果需要解析相对路径,则必须搜索PATH手动。

如果你想运行一个程序相对于Python脚本的位置, use __file__然后从那里找到程序的绝对路径,然后在中使用绝对路径Popen.

在当前进程的环境变量中搜索PATH

Python 错误跟踪器中的一个问题关于 Python 如何处理裸命令(无斜杠)。基本上,在 Unix/Mac 上Popen表现得像os.execvp当争论env=None(在最后观察到并记录了一些意想不到的行为):

在 POSIX 上,该类使用os.execvp()-类似的行为来执行子程序。

这实际上对两者都是如此shell=False and shell=True, 假如env=None。函数文档中解释了此行为的含义os.execvp:

末尾处包含“p”的变体(execlp(), execlpe(), execvp(), and execvpe())将使用PATH用于定位程序的环境变量file。当环境被替换时(使用其中之一exec*e变体,将在下一段中讨论),新环境被用作PATH多变的。

For execle(), execlpe(), execve(), and execvpe()(请注意,这些都以“e”结尾),env参数必须是用于定义新进程的环境变量的映射(这些变量用于代替当前进程的环境);功能execl(), execlp(), execv(), and execvp()都会导致新进程继承当前进程的环境。

引用的第二段意味着execvp将使用当前进程的环境变量。结合第一段引用的段落,我们推断出execvp将使用环境变量的值PATH来自当前进程的环境。这意味着Popen看看的价值PATH 就像 Python 刚推出时一样(运行的PythonPopen实例化)并且没有任何改变os.environ会帮助你解决这个问题。

另外,在 Windows 上shell=False, Popen不注意PATH根本不会,并且只会相对于当前工作目录进行查找。

What shell=True does

如果我们通过会发生什么shell=True to Popen?在这种情况下,Popen只需调用 shell:

The shell参数(默认为False) 指定是否使用shell作为程序来执行。

也就是说,Popen相当于:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

换句话说,与shell=TruePython会直接执行/bin/sh,无需任何搜索(传递参数executable to Popen可以改变这一点,似乎如果它是一个没有斜杠的字符串,那么它会被Python解释为shell程序的名称来在值中搜索PATH从当前进程的环境中,即在该情况下搜索程序时shell=False如上所述)。

反过来,/bin/sh(或者我们的外壳executable)将寻找我们想要在其自己的环境中运行的程序PATH,这与PATHPython(当前进程)的,从上面短语“也就是说...”之后的代码推导出来(因为该调用有shell=False,所以这是前面已经讨论过的情况)。因此,execvp-类似的行为是我们从两者中得到的shell=True and shell=False, 只要env=None.

Passing env to Popen

那么如果我们通过了会发生什么env=dict(PATH=...) to Popen(因此定义一个环境变量PATH在将要运行的程序的环境中Popen)?

在这种情况下,新环境用于搜索要执行的程序。引用文档Popen:

If env is not None,它必须是一个定义新进程的环境变量的映射;这些用于代替继承当前进程环境的默认行为。

结合上述观察,并通过实验使用Popen, 这意味着Popen在这种情况下,其行为类似于函数os.execvpe. If shell=False, Python 在新定义的中搜索给定的程序PATH。正如上面已经讨论过的shell=True,在这种情况下,程序是/bin/sh,或者,如果程序名称与参数一起给出executable,然后在新定义的中搜索这个替代(shell)程序PATH.

另外,如果shell=True, then 壳内shell 将用来查找给出的程序的搜索路径args的值是PATH传递给Popen via env.

So with env != None, Popen搜索键的值PATH of env(如果有钥匙PATH存在于env).

传播除以下之外的环境变量PATH作为参数

关于环境变量有一个警告,除了PATH:如果命令中需要这些变量的值(例如,作为正在运行的程序的命令行参数),那么即使这些变量存在于env给予Popen,如果没有,它们将不会被解释shell=True。 这很容易避免,无需更改shell=True:将这些值直接插入list争论args被赋予Popen。 (另外,如果这些值来自Python自己的环境,则该方法os.environ.get可以用来获取它们的值)。

Using /usr/bin/env

如果您只是需要路径评估并且并不真正想通过 shell 运行命令行,并且使用的是 UNIX,我建议使用env代替shell=True, as in

path = '/dir1:/dir2'
subprocess.Popen(['/usr/bin/env', '-P', path, 'progtorun', other, args], ...)

这可以让你通过一个不同的PATH to the env过程(使用选项-P),它将使用它来查找程序。它还避免了 shell 元字符的问题以及通过 shell 传递参数的潜在安全问题。显然,在 Windows 上(几乎是唯一没有/usr/bin/env)你需要做一些不同的事情。

About shell=True

引用Popen文档:

If shell is True,建议通过args作为字符串而不是序列。

Note:阅读安全考虑使用前的部分shell=True.

意外的观察结果

观察到以下行为:

  • 这个呼吁引发了FileNotFoundError,正如预期的那样:

    subprocess.call(['sh'], shell=False, env=dict(PATH=''))
    
  • 这个调用发现sh,这是意想不到的:

    subprocess.call(['sh'], shell=False, env=dict(FOO=''))
    

    Typing echo $PATH在打开的外壳内显示PATHvalue 不为空,也不同于PATH在Python环境中。所以看来PATH确实不是从 Python 继承的(正如预期的那样,存在env != None),但是,它仍然是PATH是非空的。不知道为什么会出现这种情况。

  • 这个呼吁引发了FileNotFoundError,正如预期的那样:

    subprocess.call(['tree'], shell=False, env=dict(FOO=''))
    
  • 这发现tree,正如预期的那样:

    subprocess.call(['tree'], shell=False, env=None)
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python子进程Popen环境路径? 的相关文章

随机推荐

  • Google App Engine 自定义域未激活 Google 管理的 SSL

    我在 Google App Engine 上成功为我的应用程序配置了自定义域 我可以通过以下方式访问我的应用程序 http www myapp com 但是 在我的自定义域仪表板上 Google 管理的 SSL 需要很长时间才能激活 我有一
  • 一点到这条曲线的最短距离

    我需要找到多个点到以下形式的曲线的距离 f x a k bx 我的第一个选择是使用它的导数 使用导数的倒数形式的线 给出它的坐标Point并将其与原始曲线相交 最后 我们用简单的几何计算点之间的距离 这就是我通常遵循的数学过程 我需要节省时
  • 在证书上,主题AltName 中的电子邮件地址应为什么类型

    一点背景 我正在建造一个证书颁发机构使用 M2Crypto 和 Django 所以请在投票之前三思而后行 将其视为题外话 我的方法是 最终用户通过电子邮件地址进行识别 并且他们的自签名信任锚显然是由他们自己发布的 但我应该如何存储他们的 身
  • XML 中的转义双引号字符

    xml中的双引号是否有转义字符 我想写一个标签 例如
  • 最短超串搜索的更有效算法

    我下面的问题是 NP 完全的 但是 我试图找到至少稍微快一点的字符串搜索函数或模块 与现在相比 它可能有助于减少一些计算时间 任何建议 将不胜感激 连接的 尽可能长的 超字符串是 AGGAGTCCGCGTGAGGGAGGTGTAGTGTAG
  • 如何在 python 中构造列表项的集合?

    我有一个listpython 中的文件名 我想构造一个set从所有文件名中 filelist for filename in filelist set filename 这似乎不起作用 怎么能做到这一点呢 如果您有一个可哈希对象的列表 文件
  • 为什么分支名称不能在开头包含“#”字符?

    这个 git checkout b 1 my awesome feature 产生错误 error switch b requires a value 用反斜杠转义或用引号括起来都可以 git checkout b 1 my awesome
  • 在 Symfony2 中验证密码

    我正在尝试在 Symfony2 中整合更改密码功能 我有一个 当前密码 字段 一个 新密码 字段和一个 确认新密码 字段 我当前关注的部分是验证 当前密码 字段 顺便说一句 我现在意识到像这样的事情FOSUserBundle存在 可以为我处
  • 如何在 Laravel 5+ 中获取客户端 IP 地址

    我正在尝试在 Laravel 中获取客户端的 IP 地址 在 PHP 中使用以下命令可以轻松获取客户端的 IP SERVER REMOTE ADDR 它在核心 PHP 中工作正常 但是当我在 Laravel 中使用相同的东西时 它返回服务器
  • 在浏览器下载中保留 UTF-8 BOM

    我有一个 JAX RS REST Service 它生成 CSV 文件并将其流回浏览器 一切都设置为 UTF 8 所以我通过浏览器下载的文件也是一个有效的 UTF 8 文件 没有 BOM 它在 Notepad Sublime 等中向我显示有
  • java.lang.IllegalArgumentException:当前应该 >= start 且 <= end

    我正在尝试在 android 中的按钮上实现日期选择器 但一旦我点击按钮 错误就会弹出 但时间选择器运行良好 这是代码 mPickDate setOnClickListener new View OnClickListener Assign
  • 从 ggplot2 图例中删除“点”元素

    示例代码 EmigProb lt c rep seq 0 1 0 8 length 5 4 rep seq 0 1 0 8 length 5 4 RemainEmigProb lt c rep 0 2 5 rep 0 4 5 rep 0 6
  • Python 中基于 Web 的聊天服务器的教程 [已关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我正在做一个网络课程的家庭作业项目 我们必须用 C C 或 Python 构建一个简单的基于 Web 的聊天服务器 我选择 Python 是因为我认
  • AVCaptureSession stopRunning 方法会造成严重的挂起

    Using iOS 7 教程第 22 章中的 Raywenderlich 二维码阅读器 我成功读取当前应用程序的二维码 我现在扩展它 在成功读取二维码后 我想存储stringValue of the AVMetadataMachineRea
  • 间隔顺序统计

    给定一个数字数组a 0 a 1 a n 1 我们得到这样的查询 output k 范围内的最大数字a i a i 1 a j 这些问题能否在多对数时间内得到回答 在n 每个查询 如果不是 是否有可能对结果进行平均并仍然获得良好的摊余复杂度
  • 具有直接像素访问的 Opencv 颜色映射

    我有一个灰度图像 我想通过将灰度值映射到调色板 如 Matlab 中的颜色图 来以彩色显示 我设法使用 OpenCV 做到了cvSet2D函数 但出于性能原因我想直接访问像素 但当我这样做时 图像有奇怪的颜色 我尝试以不同的顺序设置颜色 R
  • WPF 中文本框中的 ScrollToCaret 位于何处?

    我无法找到该功能 基本上我有一个多行文本框 当我执行搜索时 我会突出显示结果 但是 如果结果不在视图中 我将不得不手动向下滚动 直到找到突出显示的结果 这超出了 查找 功能的目的 我不想使用 RichTextBox 因为我遇到了一些性能问题
  • PHP PDO 获取 null

    如何检查列值是否为空 示例代码 db DBCxn getCxn sql SELECT exercise id author id submission result submission time total rating votes to
  • 单击按钮时呈现部分视图

    我有索引视图 using System Web Mvc Html model MsmqTestApp Models MsmqData Scripts jquery unobtrusive ajax min js type text java
  • python子进程Popen环境路径?

    假设有一个可执行文件和一个用于启动它的 Python 脚本 并且它们位于 兄弟 子目录中 例如 tmp subdir1 myexecutable tmp subdir2 myscript py If in tmp和跑步python subd