如何将 sh -c "$(curl -fsSL URL)" 转换为原生 python

How to convert sh -c "$(curl -fsSL URL)" to native python

我正在尝试转换 shell 命令:

sh -c "$(curl -fsSL https://raw.githubusercontent.com/foo/install.sh)"

为原生 python。我不能依赖系统上的 curl。我从这个开始替换 curl

from urllib.request import urlretrieve
from urllib.error import URLError

try:
    urlretrieve("https://raw.githubusercontent.com/foo/install.sh",
                        os.path.expanduser('~/' + 'install.sh'))
except URLError as e:
...

然后在本机 python 中复制命令的 sh -c install.sh 部分的最佳方法是什么?我需要一个交互式 shell 到 install.sh,然后脚本才能在 python 中继续。我需要一个 python 带有异常处理的交互式子进程来执行 install.sh

子流程的一些例子?

import subprocess
p = subprocess.Popen(['sh install.sh'], 
            stdout=subprocess.PIPE, 
            stderr=subprocess.STDOUT)
stdout,stderr = p.communicate()
print(stdout)
print(stderr)

另一种不等待命令完成就写出

import subprocess, sys
cmd = "sh install.sh"
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)

while True:
    out = p.stderr.read(1)
    if out == '' and p.poll() != None:
        break
    if out != '':
        sys.stdout.write(out)
        sys.stdout.flush()

您可以尝试os.system(),即在当前目录下保存安装脚本后,

os.system('sh -c install.sh')

该脚本大概是用 sh 编写的,因此您需要 sh(或兼容)到 运行 它。

它使用 stdin/stdout,因此您可以在必要时使用终端与其进行交互。当子进程终止时,os.system() returns 它的退出代码和 Python 恢复。

(如果您不保存到工作目录,您可以使用 install.sh 的绝对路径,或使用 os.chdir() 更改工作目录。)

如果您需要在 Python 中自动执行此交互,您可能应该改用 subprocess,它更强大,但需要更多的配置工作。


Yes, I need to run sh and os.system() is the easiest way. I would like the script to run unattended and only prompt user if input is needed. I will expand on my question with a subprocess example.

如果脚本 运行 在没有进一步输入的正常情况下自行终止,那么 os.system() 就足够了,即使 运行 无人看管,因为 Python 将在脚本完成时恢复。如果需要,您还可以为非零退出代码引发异常:

if os.system('sh -c install.sh'): raise ...