来自外部程序的交互式 writing/reading
Interactively writing/reading from an external program
背景故事:我是 Python 的新手,但对 Perl 相当有经验。我正在努力使我在系统管理员活动领域的脚本组合多样化。
我正在尝试通过我的 python 脚本与外部进程进行动态通信。
我想做的是:
- 调用一个可执行文件(让我们称之为"cli")
- 写一行到cli
- 在内部读回响应
- 逐个遍历响应,并将另一行写入 CLI
- 将 cli 的响应打印回控制台
我希望这会产生的结果是:
(spawn process) /usr/local/bin/cli
-> show listofobjects
<- (read back list of objects internally)
-> (one by one, write a line to the cli for each of the list of objects)
-> get objectname modifiedtime
<- (print response from above command)
这是我目前的代码:
import shlex, subprocess, re
clicmd = "/usr/local/bin/cli -s 10.1.213.226 -n Administrator -p password"
cliargs = shlex.split(clicmd)
cliproc = subprocess.Popen(cliargs,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
tmpclicmd = "LIST objects OUTPUT csv NAME"
cliret = cliproc.communicate(input=tmpclicmd)[0]
regex = re.compile('^\".*')
for line in cliret.split('\n'):
if regex.match(line):
procline = line.replace('"','')
if 'NAME' not in procline:
clideets = subprocess.Popen(cliargs,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
clideetscmd = 'modify objects ' + procline
clideets.communicate(input=clideetscmd)
clideetscmd = 'list objectdetails'
clideetsresp = clideets.communicate(input=clideetscmd)[0]
print clideetsresp;
我可能以完全错误的方式解决这个问题。我是否必须为每一步生成一个新的 Popen?我怎样才能做得更好? (另一个模块等)。在一天结束的时候,我无法让 cli 关闭,而 Popen 似乎在每一步之后都会这样做。
提前致谢!
不必为每次交互都启动一个新进程(使用 Popen
)。但是,当您使用 communicate
将数据发送到进程时,您会这样做,因为正如文档所述:
Interact with process: Send data to stdin. Read data from stdout and
stderr, until end-of-file is reached. Wait for process to terminate.
相反,只需写入 cliproc.stdin
并从 cliproc.stdout
读取:
cliproc.stdin.write("LIST objects OUTPUT csv NAME")
cliret = cliproc.stdout.readline()
进程以这种方式保持活动状态。
我不知道你为什么在这里使用shlex
模块:
clicmd = "/usr/local/bin/cli -s 10.1.213.226 -n Administrator -p password"
cliargs = shlex.split(clicmd)
内置的str.split
方法就可以了:
clicmd = "/usr/local/bin/cli -s 10.1.213.226 -n Administrator -p password"
cliargs = clicmd.split()
或者您可以自己编写结果列表:
cliargs = ["/usr/local/bin/cli", "-s", "10.1.213.226",
"-n", "Administrator", "-p", "password"]
这里不需要分号:
print clideetsresp;
背景故事:我是 Python 的新手,但对 Perl 相当有经验。我正在努力使我在系统管理员活动领域的脚本组合多样化。
我正在尝试通过我的 python 脚本与外部进程进行动态通信。
我想做的是:
- 调用一个可执行文件(让我们称之为"cli")
- 写一行到cli
- 在内部读回响应
- 逐个遍历响应,并将另一行写入 CLI
- 将 cli 的响应打印回控制台
我希望这会产生的结果是:
(spawn process) /usr/local/bin/cli
-> show listofobjects
<- (read back list of objects internally)
-> (one by one, write a line to the cli for each of the list of objects)
-> get objectname modifiedtime
<- (print response from above command)
这是我目前的代码:
import shlex, subprocess, re
clicmd = "/usr/local/bin/cli -s 10.1.213.226 -n Administrator -p password"
cliargs = shlex.split(clicmd)
cliproc = subprocess.Popen(cliargs,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
tmpclicmd = "LIST objects OUTPUT csv NAME"
cliret = cliproc.communicate(input=tmpclicmd)[0]
regex = re.compile('^\".*')
for line in cliret.split('\n'):
if regex.match(line):
procline = line.replace('"','')
if 'NAME' not in procline:
clideets = subprocess.Popen(cliargs,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
clideetscmd = 'modify objects ' + procline
clideets.communicate(input=clideetscmd)
clideetscmd = 'list objectdetails'
clideetsresp = clideets.communicate(input=clideetscmd)[0]
print clideetsresp;
我可能以完全错误的方式解决这个问题。我是否必须为每一步生成一个新的 Popen?我怎样才能做得更好? (另一个模块等)。在一天结束的时候,我无法让 cli 关闭,而 Popen 似乎在每一步之后都会这样做。
提前致谢!
不必为每次交互都启动一个新进程(使用
Popen
)。但是,当您使用communicate
将数据发送到进程时,您会这样做,因为正如文档所述:Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate.
相反,只需写入
cliproc.stdin
并从cliproc.stdout
读取:cliproc.stdin.write("LIST objects OUTPUT csv NAME") cliret = cliproc.stdout.readline()
进程以这种方式保持活动状态。
我不知道你为什么在这里使用
shlex
模块:clicmd = "/usr/local/bin/cli -s 10.1.213.226 -n Administrator -p password" cliargs = shlex.split(clicmd)
内置的
str.split
方法就可以了:clicmd = "/usr/local/bin/cli -s 10.1.213.226 -n Administrator -p password" cliargs = clicmd.split()
或者您可以自己编写结果列表:
cliargs = ["/usr/local/bin/cli", "-s", "10.1.213.226", "-n", "Administrator", "-p", "password"]
这里不需要分号:
print clideetsresp;