如何从 python 脚本成功调用 gsutil rsync?

Posted

技术标签:

【中文标题】如何从 python 脚本成功调用 gsutil rsync?【英文标题】:How do you successfully invoke gsutil rsync from a python script? 【发布时间】:2019-03-20 13:06:48 【问题描述】:

我正在尝试执行以下行

gsutil -m rsync s3://input gs://output

在 python 中。在 shell 终端中运行此行时,它工作正常。但是,我正在尝试使用以下行在 python 脚本中运行它。

subprocess.Popen(["gsutil", "-m", "rsync", "s3://input", "gs://output"])

但是它只是永远挂起。它输出以下内容:

Building synchronization state...
Starting synchronization...

bash 命令成功打印:

Building synchronization state...
Starting synchronization...
Copying s3://input/0000
[0/1 files][  1.0 MiB/ 5.1 MiB]   (number here)% Done

文件显示在我的 gs 存储桶中

【问题讨论】:

【参考方案1】:

我猜这是因为最后两行可能是写入 stderr 而不是 stdout。您可以尝试使用对Popen 的调用作为上下文管理器,然后调用communicate() 从输出流中读取吗?

proc = subprocess.Popen(["gsutil", "-m", "rsync", "s3://input", "gs://output"])
try:
    outs, errs = proc.communicate(timeout=15)
    # now you can do something with the text in outs and errs
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

【讨论】:

啊,这与 subprocess.TimeoutExpired 的警告一起工作,但我很好奇为什么。当 gsutil rsync 拉取文件并显示进度条时,15 秒后它会超时,然后 shell 将返回给我,但进度条时间会一直被推到屏幕上。我不明白 proc.kill() 如何不阻止 gsutil rsync 继续,除非子进程不是在两个存储桶上运行 gsutil rsync 的东西? 您也可以将 stderr 和 stdout 结合起来,如下所述:***.com/questions/6809590/…。至于proc.kill(),您可能希望在使用 SIGKILL 放下锤子之前让子进程有机会进行适当的清理(通过proc.terminate() 发送SIGTERM)。由于您没有指定将输出发送到的管道,因此子进程将输出发送到其父级的 stdout/stderr - 当您在发送 SIGTERM 后调用 communicate() 时,它会读取 stdout/stderr 输出直到子进程最终终止跨度>

以上是关于如何从 python 脚本成功调用 gsutil rsync?的主要内容,如果未能解决你的问题,请参考以下文章

从 groovy 脚本运行 gsutil:找不到 Python 可执行文件

带有 python 入口点的 Google Cloud Build gsutil

在 python 脚本中运行 gcloud auth 和 gsutil 命令

当 Python 3.5.2 调用 gsutil rsync 时返回错误,但从命令行可以

Python中的gsutil引发语法错误

使用 python 子进程在实例上运行 gsutil - 访问权限?