简体   繁体   English

调用 subprocess.call(['.', bash_path]) 时权限被拒绝

[英]Permission denied when calling subprocess.call(['.', bash_path])

When I run the following code当我运行以下代码时

import os
import subprocess

bash_path = os.path.expanduser('~/.bash_profile')
subprocess.call(['.',  bash_path])

I get the following error:我收到以下错误:

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: '.'

I have also tried the variation subprocess.call(['source', bash_path]) , but I get the same results with source replacing .我也尝试了变体subprocess.call(['source', bash_path]) ,但我得到了相同的结果,使用source替换. . . It appears that from the python script I don't have permissions to call source or .从 python 脚本看来,我无权调用source. , but from my terminal I do. ,但从我的终端我做。

I'm trying to reload my environment variables because my program calls another subprocess before this that updates some configuration variables, however, they're not available until I either re- source them, or restart the terminal.我想重装我的环境变量,因为我的程序这一点,更新一些配置变量之前调用另一个子,但是,他们并不可用,直到我要么重新source他们,或重新启动终端。

How can I re- source my .bash_profile from within a python script?如何从 python 脚本中获取我的.bash_profile source

There are two issues here:这里有两个问题:

  1. . (and its alias, source ) are not programs which could be executed by execv (or subprocess in Python). (及其别名source )不是可以由execv (或 Python 中的subprocess execv执行的程序。 They are shell built-ins.它们是 shell 内置的。

  2. Not coincidentally, .并非巧合, . cannot be implemented by an external program, which is why it is built-in to the shell.不能由外部程序实现,这就是它内置于 shell 的原因。

The first one explains why you cannot use subprocess.call to execute .第一个解释了为什么不能使用subprocess.call来执行. or source .source subprocess.call can only execute external programs. subprocess.call只能执行外部程序。 It cannot execute a shell built-in, because there is no shell;它不能执行内置的shell,因为没有shell; subprocess.call is running inside a Python program, not a shell. subprocess.call在 Python 程序中运行,而不是在 shell 中运行。 So when you try to subprocess.call('.',...) , you are trying to execute .因此,当您尝试subprocess.call('.',...) ,您正在尝试执行. , which is a directory. ,这是一个目录。 Saying that you don't have permissions to run a directory is technically true, but not very useful as an error message;说您没有运行目录的权限在技术上是正确的,但作为错误消息并不是很有用; directories cannot be executed, even by the root user.目录不能被执行,即使是 root 用户。 I would expect subprocess.call(['source', ...]) to produce a "no such file or directory" error, but perhaps you have a file called source (without execution permissions) somewhere in your execution path.我希望subprocess.call(['source', ...])产生“没有这样的文件或目录”错误,但也许您的执行路径中某处有一个名为source (没有执行权限)的文件。 (Not a good idea, since source is commonly used as a shell built-in.) (这不是一个好主意,因为source通常用作内置的 shell。)

But it is really the second issue which is key.但真正关键的是第二个问题。 An external program, even one running as a child, cannot reach into the process in which Python is running and retroactively change the process environment variables.外部程序,即使是小时候运行的程序,也无法进入 Python 运行的进程并追溯更改进程环境变量。 (Or, for that matter, the current working directory, which is why you can't subprocess.call the cd command.) (或者,就此而言,当前工作目录,这就是您不能subprocess.call cd命令的原因。)

Environment variables are so-called because they are part of the execution environment .所谓环境变量,是因为它们是执行环境的一部分。 The execution environment is created along with a process, or perhaps it would be better to say that part of a process is the execution environment.执行环境是与流程一起创建的,或者说流程的一部分是执行环境会更好。 Most of the execution environment is inherited from the process parent.大多数执行环境是从进程父级继承的。 But that does not mean that a process shares its environment with its children.但这并不意味着进程与其子进程共享其环境。 Rather, the process copies its environment into the new environment created for the child.相反,该过程将其环境复制到为孩子创建的新环境中。 So environment variables are passed from parent to child, but the child's variables are its own independent variables;所以环境变量是从父级传给子级的,但是子级的变量是自己的自变量; changing them does not affect the parent's environment variables, nor the environment variables of its already spawned children.更改它们不会影响父级的环境变量,也不会影响其已经生成的子级的环境变量。

When you start a new "login shell" (which is the process which negotiates with the OS to allow you to log in), that shell executes your profile script, which customises the shell's execution environment.当您启动一个新的“登录外壳”(这是与操作系统协商以允许您登录的过程)时,该外壳会执行您的配置文件脚本,该脚本自定义外壳的执行环境。 (If your shell is bash , it will use the bash-specific profile ~/.bash_profile script, if it exists.) From there on, newly created children of that shell -- which includes all the other processes you start, including graphical console sessions -- are started with a copy of this execution environment. (如果您的 shell 是bash ,它将使用特定于 bash 的配置文件~/.bash_profile脚本,如果它存在。)从那时起,该 shell 的新创建的子级 - 包括您启动的所有其他进程,包括图形控制台会话——从这个执行环境的副本开始。

The execution of the profile script must be done with .配置文件脚本的执行必须使用. (or equivalent) because the intent is to change the current execution environment. (或等效的),因为目的是改变当前的执行环境。 . can do that, because it is a bash command, not an external command running in a subprocess.可以这样做,因为它是一个 bash 命令,而不是在子进程中运行的外部命令。 It just executes each shell command in the given script as though you had typed it directly, so that it happens inside the current execution environment.它只是执行给定脚本中的每个 shell 命令,就像您直接键入它一样,因此它发生在当前执行环境中。 But Python does not have any equivalent.但是 Python 没有任何等价物。 Python is not a bash shell, and it has no idea what any bash command line means. Python 不是 bash shell,它不知道任何 bash 命令行意味着什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM