python os 和命令行引号的不同解释
Different interpretation of quotes from python os and command line
我是 运行 一个 python3 脚本,它在 Debian 9 上执行以下片段:
os.environ["PA_DIR"] = "/home/myname/some_folder"
command_template = ("sudo java -Dconfig.file=$PA_DIR/google.conf "
"-jar ~/big/cromwell-42.jar run $PA_DIR/WholeGenomeGermlineSingleSample.wdl "
"-i {} -o $PA_DIR/au_options.json > FDP{}.log 2>&1")
command = command_template.format("test.json, "1")
os.system("screen -dm -S S{} bash -c '{}'".format("1", command))
PA_DIR 的使用按预期工作。当我在命令行上尝试时:
PA_DIR="/home/myname/some_folder"
screen -dm -S S1 bash -c 'sudo java -Dconfig.file=$PA_DIR/google.conf -jar ~/big/cromwell-42.jar run $PA_DIR/WholeGenomeGermlineSingleSample.wdl -i test.json -o $PA_DIR/au_options.json > FDP1.log 2>&1'
由于单引号,它没有进行变量替换,我不得不用双引号替换它们(它抱怨找不到文件 /google.conf)。
python 运行时有什么不同?
谢谢!
Python os.system()
调用 C 库的底层 system
函数,在 POSIX 系统上相当于做类似
的事情
sh -c "your_command and all its arguments"
所以命令和所有参数已经被 double-quotes 包围,它进行环境变量替换。字符串中的任何单引号与变量替换无关。
您可以轻松测试它。在 shell 中做类似
的事情
$ foo="bar"
$ echo "foo is '$foo'" # Will print foo is 'bar'
$ echo 'foo is "$foo"' # Will print foo is "$foo"
等待您对 daltonfury42 的回答,我敢打赌问题是,当在命令行中 运行ning 时,您没有导出 PA_DIR 环境变量,因此它不存在于第二个 bash 口译员。由于 Mihir 的回答,它的行为有所不同。
如果你运行
PA_DIR=foo
你只声明了一个 bash 变量,但它不是环境变量。然后
bash -c "echo $PA_DIR"
这将输出 foo,因为您当前的解释器插入 $PA_DIR
,然后使用命令 echo foo
引发第二个 bash 进程。但是
bash -c 'echo $PA_DIR'
这会阻止您的 bash 解释器对其进行插值,因此它会使用命令 echo $PA_DIR
引发第二个 bash 进程。但是在第二个过程中,变量 PA_DIR 不存在。
如果你开始你的旅程运行宁
export PA_DIR=foo
这将成为子进程可以访问的环境变量,因此
bash -c 'echo $PA_DIR'
将输出 foo,因为嵌套的 bash 解释器可以访问变量,即使父 bash 解释器没有插入它。
任何种类的子进程也是如此。尝试 运行宁
PA_DIR=foo
python3 -c 'import os; print(os.environ.get("PA_DIR"))'
python3 -c "import os; print(os.environ.get('PA_DIR'))"
export PA_DIR=foo
python3 -c 'import os; print(os.environ.get("PA_DIR"))'
python3 -c "import os; print(os.environ.get('PA_DIR'))"
在你的 shell 中。此处不涉及引号!
当您在 Python 脚本中使用 os.environ
字典时,Python 会为您导出变量。这就是为什么你会看到由
插入的变量
os.system("bash -c 'echo $PA_DIR'")
或
os.system('bash -c "echo $PA_DIR"')
但请注意,在每种情况下,插入变量的是父进程或子进程 shell。
你必须在这里了解你的进程树:
/bin/bash # but it could be a zsh, fish, sh, ...
|- /usr/bin/python3 # presumably
|- /bin/sh # because os.system uses that
|- /bin/bash
如果你想让一个环境变量存在于最嵌套的进程中,你必须将它导出到上层树的任何位置。或者在那个过程中。
我是 运行 一个 python3 脚本,它在 Debian 9 上执行以下片段:
os.environ["PA_DIR"] = "/home/myname/some_folder"
command_template = ("sudo java -Dconfig.file=$PA_DIR/google.conf "
"-jar ~/big/cromwell-42.jar run $PA_DIR/WholeGenomeGermlineSingleSample.wdl "
"-i {} -o $PA_DIR/au_options.json > FDP{}.log 2>&1")
command = command_template.format("test.json, "1")
os.system("screen -dm -S S{} bash -c '{}'".format("1", command))
PA_DIR 的使用按预期工作。当我在命令行上尝试时:
PA_DIR="/home/myname/some_folder"
screen -dm -S S1 bash -c 'sudo java -Dconfig.file=$PA_DIR/google.conf -jar ~/big/cromwell-42.jar run $PA_DIR/WholeGenomeGermlineSingleSample.wdl -i test.json -o $PA_DIR/au_options.json > FDP1.log 2>&1'
由于单引号,它没有进行变量替换,我不得不用双引号替换它们(它抱怨找不到文件 /google.conf)。 python 运行时有什么不同? 谢谢!
Python os.system()
调用 C 库的底层 system
函数,在 POSIX 系统上相当于做类似
sh -c "your_command and all its arguments"
所以命令和所有参数已经被 double-quotes 包围,它进行环境变量替换。字符串中的任何单引号与变量替换无关。
您可以轻松测试它。在 shell 中做类似
的事情$ foo="bar"
$ echo "foo is '$foo'" # Will print foo is 'bar'
$ echo 'foo is "$foo"' # Will print foo is "$foo"
等待您对 daltonfury42 的回答,我敢打赌问题是,当在命令行中 运行ning 时,您没有导出 PA_DIR 环境变量,因此它不存在于第二个 bash 口译员。由于 Mihir 的回答,它的行为有所不同。
如果你运行
PA_DIR=foo
你只声明了一个 bash 变量,但它不是环境变量。然后
bash -c "echo $PA_DIR"
这将输出 foo,因为您当前的解释器插入 $PA_DIR
,然后使用命令 echo foo
引发第二个 bash 进程。但是
bash -c 'echo $PA_DIR'
这会阻止您的 bash 解释器对其进行插值,因此它会使用命令 echo $PA_DIR
引发第二个 bash 进程。但是在第二个过程中,变量 PA_DIR 不存在。
如果你开始你的旅程运行宁
export PA_DIR=foo
这将成为子进程可以访问的环境变量,因此
bash -c 'echo $PA_DIR'
将输出 foo,因为嵌套的 bash 解释器可以访问变量,即使父 bash 解释器没有插入它。
任何种类的子进程也是如此。尝试 运行宁
PA_DIR=foo
python3 -c 'import os; print(os.environ.get("PA_DIR"))'
python3 -c "import os; print(os.environ.get('PA_DIR'))"
export PA_DIR=foo
python3 -c 'import os; print(os.environ.get("PA_DIR"))'
python3 -c "import os; print(os.environ.get('PA_DIR'))"
在你的 shell 中。此处不涉及引号!
当您在 Python 脚本中使用 os.environ
字典时,Python 会为您导出变量。这就是为什么你会看到由
os.system("bash -c 'echo $PA_DIR'")
或
os.system('bash -c "echo $PA_DIR"')
但请注意,在每种情况下,插入变量的是父进程或子进程 shell。
你必须在这里了解你的进程树:
/bin/bash # but it could be a zsh, fish, sh, ...
|- /usr/bin/python3 # presumably
|- /bin/sh # because os.system uses that
|- /bin/bash
如果你想让一个环境变量存在于最嵌套的进程中,你必须将它导出到上层树的任何位置。或者在那个过程中。