如何在Python中链接多个命令行响应?

时间:2018-02-27 17:44:21

标签: python shell command-line

我一直试图在另一个python脚本中运行脚本而没有运气。

我试图运行的脚本是garminbackup.py,可以在以下repo中找到。

https://github.com/petergardfjall/garminexport

当您从命令行运行此脚本时,它会要求您提供一些信息,用户名,保存文件的位置等等...

command = 'python garminbackup.py --backup-dir=Name email --format tcx'

然后它要求输入密码,一旦输入密码,就开始将garmin文件下载到提供的目录中。我的目标是创建一个程序,它循环遍历多个帐户并更新每个文件夹中的数据。

我的问题是我似乎无法在python中获得子进程模块来实现这一点。

我尝试了以下命令但没有运气。它似乎卡在输入密码输入屏幕上,并没有做任何其他事情。

import subprocess,shlex
from subprocess import PIPE,call
import os

p = subprocess.Popen(command,stdout=subprocess.PIPE,stdin=subprocess.PIPE,shell=True)
p.stdin.write("password\n")
p.wait()

我搜索了几个小时没有运气。任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

尽管OP通过使用--password选项解决了该问题,但其他人可能会偶然遇到相同的问题,并且已经pointed out by HuStmpHrr的情况下,在命令行中传递密码不是一个好主意。

为什么它不起作用

被调用的脚本,在这种情况下,garminbackup.py使用getpass。正如文档中所暗示的,getpass的实现比仅仅阅读stdin更复杂:

  

[...]在Unix上,提示被写入类似文件的对象流中。   流默认为控制终端(/ dev / tty),或者   sys.stderr不可用(在Windows上将忽略此参数)。

     

如果没有无回声输入,getpass()将退回到打印   警告消息流并从sys.stdin中读取并发出   GetPass警告。

应该如何工作

我们可以模拟一个虚拟终端,但是如果没有一个库,那就太复杂了(请参阅下一章)。

另一种方法是摆脱存在终端的信息(“如果无回声输入不可用”)。事实证明,这比我想象的要难,通常以cat | command | cat的身份运行命令应该摆脱tty检测,但是getpass要么变得聪明要么就变得无知,无法改变其行为。

更好的方法:期待

已经mentioned by LohmarASHAR,如果可以使用pexpectpip install pexpect),则应该使用。正是为此而做的,它将涵盖所有极端情况。

  

例如:

child = pexpect.spawn('scp foo user@example.com:.')
child.expect('Password:')
child.sendline(mypassword)
     

此功能甚至适用于要求输入密码或其他输入的命令   常规stdio流之外。例如,ssh读取输入   直接从绕过标准输入的TTY设备开始。

使用OP的示例,但要使用pexpect:

#!/usr/bin/env python

import pexpect

command = 'python garminbackup.py --backup-dir=Name email --format tcx'

p = pexpect.spawn(command)  # instead of subprocess.Popen
p.expect(":")               # This is waiting for the prompt "Enter password:", but I rather only use ":" to cope with internationalisation issues
p.sendline("password")
print p.read()              # Output the sub-processes output 
p.wait()