cof*_*fee 32 python unix popen
我有一个.sh脚本,我打电话给source the_script.sh.定期打电话很好.但是,我试图通过我的python脚本调用它subprocess.Popen.
从Popen调用它,我在以下两个场景调用中遇到以下错误:
foo = subprocess.Popen("source the_script.sh")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/subprocess.py", line 672, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1213, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
>>> foo = subprocess.Popen("source the_script.sh", shell = True)
>>> /bin/sh: source: not found
Run Code Online (Sandbox Code Playgroud)
是什么赋予了?为什么我不能从Popen中调用"source",当我可以在python之外?
Sin*_*ion 30
source 它不是一个可执行命令,它是一个内置的shell.
最常用的情况source是运行一个shell脚本来更改环境并在当前shell中保留该环境.这正是virtualenv如何修改默认的python环境.
创建子流程并source在子流程中使用可能不会做任何有用的事情,它不会修改父流程的环境,也不会发生使用源脚本的副作用.
Python有一个类似的命令,execfile它使用当前的python全局命名空间(或另一个,如果你提供的)运行指定的文件,你可以使用与bash命令类似的方式source.
xAp*_*ple 28
您可以在子shell中运行该命令,并使用结果更新当前环境.
def shell_source(script):
"""Sometime you want to emulate the action of "source" in bash,
settings some environment variables. Here is a way to do it."""
import subprocess, os
pipe = subprocess.Popen(". %s; env" % script, stdout=subprocess.PIPE, shell=True)
output = pipe.communicate()[0]
env = dict((line.split("=", 1) for line in output.splitlines()))
os.environ.update(env)
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 14
Broken Popen("source the_script.sh")相当于Popen(["source the_script.sh"])尝试启动'source the_script.sh'程序失败.它找不到它,因此"No such file or directory"错误.
破坏Popen("source the_script.sh", shell=True)失败,因为source是bash内置命令(help source在bash中键入)但默认shell是/bin/sh不理解它(/bin/sh使用.).假设可能有其他bash-ism the_script.sh,它应该使用bash运行:
foo = Popen("source the_script.sh", shell=True, executable="/bin/bash")
Run Code Online (Sandbox Code Playgroud)
正如@IfLoop所说,source在子进程中执行它并不是非常有用,因为它不会影响父进程的环境.
os.environ.update(env)如果对某些变量the_script.sh执行unset,则基于方法失败.os.environ.clear()可以调用来重置环境:
#!/usr/bin/env python2
import os
from pprint import pprint
from subprocess import check_output
os.environ['a'] = 'a'*100
# POSIX: name shall not contain '=', value doesn't contain '\0'
output = check_output("source the_script.sh; env -0", shell=True,
executable="/bin/bash")
# replace env
os.environ.clear()
os.environ.update(line.partition('=')[::2] for line in output.split('\0'))
pprint(dict(os.environ)) #NOTE: only `export`ed envvars here
Run Code Online (Sandbox Code Playgroud)
它由@unutbu使用env -0和.split('\0')建议
为了支持任意字节os.environb,json可以使用模块(假设我们使用Python版本,其中"json.dumps无法通过json.loads解析"问题是固定的):
为了避免通过管道传递环境,可以更改Python代码以在子进程环境中调用自身,例如:
#!/usr/bin/env python2
import os
import sys
from pipes import quote
from pprint import pprint
if "--child" in sys.argv: # executed in the child environment
pprint(dict(os.environ))
else:
python, script = quote(sys.executable), quote(sys.argv[0])
os.execl("/bin/bash", "/bin/bash", "-c",
"source the_script.sh; %s %s --child" % (python, script))
Run Code Online (Sandbox Code Playgroud)
source是一个特定于 bash 的内置 shell(非交互式 shell 通常是轻量级的 dash shell,而不是 bash)。相反,只需调用/bin/sh:
foo = subprocess.Popen(["/bin/sh", "the_script.sh"])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
39766 次 |
| 最近记录: |