如何从 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 命令