Broken Popen("source the_script.sh")
эквивалентно Popen(["source the_script.sh"])
, который безуспешно пытается запустить программу 'source the_script.sh'
. Это не может найти это, следовательно "No such file or directory"
ошибка.
Broken Popen("source the_script.sh", shell=True)
завершается неудачно, потому что source
является встроенной командой bash (введите help source
в bash), но оболочкой по умолчанию является /bin/sh
, которая не понимает ее (/bin/sh
использует .
). Предполагая, что в the_script.sh
может быть другой bash-ism, его следует запустить, используя bash:
foo = Popen("source the_script.sh", shell=True, executable="/bin/bash")
Как сказал @ IfLoop , не очень полезно выполнять source
в подпроцессе, потому что это не может повлиять на среду родителя.
Методы
os.environ.update(env)
завершаются неудачно, если the_script.sh
выполняет unset
для некоторых переменных. os.environ.clear()
можно вызвать для сброса окружения:
#!/usr/bin/env python
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
Используются env -0
и .split('\0')
, предложенные @ unutbu
Для поддержки произвольных байтов в os.environb
можно использовать модуль json
(при условии, что мы используем версию Python, где "json.dumps не разбирается по json.loads", проблема исправлена):
Чтобы избежать передачи среды по каналам, код Python можно изменить так, чтобы он вызывал себя в среде подпроцесса, например ::1010 *
#!/usr/bin/env python
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))