调用 subprocess.call(['.', bash_path]) 时权限被拒绝
Permission denied when calling subprocess.call(['.', bash_path])
当我运行下面的代码
import os
import subprocess
bash_path = os.path.expanduser('~/.bash_profile')
subprocess.call(['.', bash_path])
我收到以下错误:
Traceback (most recent call last):
File "/path/to/my/script/my_script.py", line 4, in my_func
subprocess.call(['.', bash_path])
File "/Users/user/miniconda3/envs/live_auction/lib/python3.7/subprocess.py", line 323, in call
with Popen(*popenargs, **kwargs) as p:
File "/Users/jisom/miniconda3/envs/live_auction/lib/python3.7/subprocess.py", line 775, in __init__
restore_signals, start_new_session)
File "/Users/jisom/miniconda3/envs/live_auction/lib/python3.7/subprocess.py", line 1522, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: '.'
我也试过变体 subprocess.call(['source', bash_path])
,但我用 source
替换 .
得到了相同的结果。从 python 脚本看来,我没有调用 source
或 .
的权限,但我可以从我的终端调用。
我正在尝试重新加载我的环境变量,因为我的程序在此之前调用了另一个子进程来更新一些配置变量,但是,在我重新 source
它们或重新启动终端。
如何从 python 脚本中重新 source
我的 .bash_profile
?
这里有两个问题:
.
(及其别名 source
)不是可以由 execv
(或 [=65 中的 subprocess
)执行的程序=]).他们是 shell built-ins.
不是巧合,.
不能通过外部程序实现,这就是为什么built-in到shell。
第一个解释了为什么不能使用subprocess.call
来执行.
或source
。 subprocess.call
只能执行外部程序。它不能执行shell built-in,因为没有shell; subprocess.call
在 Python 程序中 运行ning,而不是 shell。因此,当您尝试 subprocess.call('.',...)
时,您正在尝试执行 .
,这是一个目录。说你没有 运行 目录的权限在技术上是正确的,但作为错误消息并不是很有用;目录无法执行,即使是 root 用户。我希望 subprocess.call(['source', ...])
产生“没有这样的文件或目录”错误,但也许您的执行路径中某处有一个名为 source
的文件(没有执行权限)。 (这不是个好主意,因为 source
通常用作 shell built-in。)
但真正关键的是第二个问题。外部程序,即使 运行ning 作为 child,也无法进入 Python 正在 运行ning 的进程并追溯更改进程环境变量。 (或者,就此而言,当前工作目录,这就是为什么你不能 subprocess.call
cd
命令的原因。)
环境变量是 so-called 因为它们是 执行环境 的一部分。执行环境是随着流程一起创建的,或者说流程的一部分是执行环境更好。大部分执行环境继承自进程parent。但这并不意味着进程 共享 其环境及其 children。相反,进程 将其环境复制 到为 child 创建的新环境中。所以环境变量是从parent传递给child,但是child的变量是它自己的独立变量;更改它们不会影响 parent 的环境变量,也不会影响其已生成的 children.
的环境变量
当您开始新的“登录 shell”(这是与 OS 协商允许您登录的过程)时,shell 会执行您的配置文件脚本,自定义 shell 的执行环境。 (如果您的 shell 是 bash
,它将使用 bash-specific 配置文件 ~/.bash_profile
脚本(如果存在)。)从那里开始,新创建的 children shell -- 包括您启动的所有其他进程,包括图形控制台会话 -- 都是用这个执行环境的副本启动的。
配置文件脚本的执行必须使用 .
(或等效的)来完成,因为目的是改变当前的执行环境。 .
可以做到这一点,因为它是 bash 命令,而不是子进程中的外部命令 运行ning。它只是执行给定脚本中的每个 shell 命令,就像您直接键入它一样,因此它发生在当前执行环境中。但是 Python 没有任何等价物。 Python 不是 bash shell,它不知道任何 bash 命令行的含义。
当我运行下面的代码
import os
import subprocess
bash_path = os.path.expanduser('~/.bash_profile')
subprocess.call(['.', bash_path])
我收到以下错误:
Traceback (most recent call last):
File "/path/to/my/script/my_script.py", line 4, in my_func
subprocess.call(['.', bash_path])
File "/Users/user/miniconda3/envs/live_auction/lib/python3.7/subprocess.py", line 323, in call
with Popen(*popenargs, **kwargs) as p:
File "/Users/jisom/miniconda3/envs/live_auction/lib/python3.7/subprocess.py", line 775, in __init__
restore_signals, start_new_session)
File "/Users/jisom/miniconda3/envs/live_auction/lib/python3.7/subprocess.py", line 1522, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
PermissionError: [Errno 13] Permission denied: '.'
我也试过变体 subprocess.call(['source', bash_path])
,但我用 source
替换 .
得到了相同的结果。从 python 脚本看来,我没有调用 source
或 .
的权限,但我可以从我的终端调用。
我正在尝试重新加载我的环境变量,因为我的程序在此之前调用了另一个子进程来更新一些配置变量,但是,在我重新 source
它们或重新启动终端。
如何从 python 脚本中重新 source
我的 .bash_profile
?
这里有两个问题:
.
(及其别名source
)不是可以由execv
(或 [=65 中的subprocess
)执行的程序=]).他们是 shell built-ins.不是巧合,
.
不能通过外部程序实现,这就是为什么built-in到shell。
第一个解释了为什么不能使用subprocess.call
来执行.
或source
。 subprocess.call
只能执行外部程序。它不能执行shell built-in,因为没有shell; subprocess.call
在 Python 程序中 运行ning,而不是 shell。因此,当您尝试 subprocess.call('.',...)
时,您正在尝试执行 .
,这是一个目录。说你没有 运行 目录的权限在技术上是正确的,但作为错误消息并不是很有用;目录无法执行,即使是 root 用户。我希望 subprocess.call(['source', ...])
产生“没有这样的文件或目录”错误,但也许您的执行路径中某处有一个名为 source
的文件(没有执行权限)。 (这不是个好主意,因为 source
通常用作 shell built-in。)
但真正关键的是第二个问题。外部程序,即使 运行ning 作为 child,也无法进入 Python 正在 运行ning 的进程并追溯更改进程环境变量。 (或者,就此而言,当前工作目录,这就是为什么你不能 subprocess.call
cd
命令的原因。)
环境变量是 so-called 因为它们是 执行环境 的一部分。执行环境是随着流程一起创建的,或者说流程的一部分是执行环境更好。大部分执行环境继承自进程parent。但这并不意味着进程 共享 其环境及其 children。相反,进程 将其环境复制 到为 child 创建的新环境中。所以环境变量是从parent传递给child,但是child的变量是它自己的独立变量;更改它们不会影响 parent 的环境变量,也不会影响其已生成的 children.
的环境变量当您开始新的“登录 shell”(这是与 OS 协商允许您登录的过程)时,shell 会执行您的配置文件脚本,自定义 shell 的执行环境。 (如果您的 shell 是 bash
,它将使用 bash-specific 配置文件 ~/.bash_profile
脚本(如果存在)。)从那里开始,新创建的 children shell -- 包括您启动的所有其他进程,包括图形控制台会话 -- 都是用这个执行环境的副本启动的。
配置文件脚本的执行必须使用 .
(或等效的)来完成,因为目的是改变当前的执行环境。 .
可以做到这一点,因为它是 bash 命令,而不是子进程中的外部命令 运行ning。它只是执行给定脚本中的每个 shell 命令,就像您直接键入它一样,因此它发生在当前执行环境中。但是 Python 没有任何等价物。 Python 不是 bash shell,它不知道任何 bash 命令行的含义。