如何与Python中的其他程序交互?

时间:2011-03-07 21:34:49

标签: python linux pty

我想编写一个运行另一个程序的Python脚本,读取另一个程序的输出并进行操作。问题是这个程序提示输入密码,我无法弄清楚如何自动提供密码。 (出于这个脚本的目的,密码是否以纯文本形式存储在脚本本身中并不重要。)我想要做的是:

os.system('echo someinput | /var/local/bin/someprogram') 

这导致someprogram给我不需要的密码提示,也没有给我程序的输出作为返回值。可悲的是,程序没有办法绕过这个提示。

不幸的是,我对如何解决这个问题也有一些限制。首先,我坚持使用Python 2.3(所以我不能使用子进程模块)。其次,我无法安装任何新模块,(所以没有pexpect)。幸运的是,它不必特别便携,因此只支持Linux的解决方案就可以了。

我一直在试图弄清楚pty模块,因为看起来它提供了我需要的东西,但是在花了几个小时摔跤之后,我就无法弄清楚如何让它以我需要的方式工作

3 个答案:

答案 0 :(得分:3)

我在基于终端的进程间通信方面遇到了类似的问题,使用popen(等人)似乎无法解决这些问题。我最后通过阅读pexpect的来源学习了如何使用pty,其中包含了如何(和评论为什么)让pty跳过必要的箍的示例。

当然,根据您的需要,您也可以使用 pexpect!

这是我在自己的项目中使用的内容。请注意,我没有检查子进程是否终止;该脚本旨在作为管理长期运行的Java进程的守护进程运行,因此我从不必处理状态代码。但是,希望这能为您提供所需的大部分内容。

import os
import pty
import select
import termios

child_pid, child_fd = pty.fork()

if not child_pid: # child process
    os.execv("/path/to/command", ["command", "arg1", "arg2"])

# disable echo
attr = termios.tcgetattr(child_fd)
attr[3] = attr[3] & ~termios.ECHO
termios.tcsetattr(child_fd, termios.TCSANOW, attr)

while True:
    # check whether child terminal has output to read
    ready, _, _ = select.select([child_fd], [], [])

    if child_fd in ready:
        output = []

        try:
            while True:
                s = os.read(child_fd, 1)

                # EOF or EOL
                if not s or s == "\n":
                    break

                # don't store carriage returns (no universal line endings)
                if not s == "\r":
                    output.append(s)
        except OSError: # this signals EOF on some platforms
            pass

        if output.find("Enter password:") > -1:
            os.write(child_fd, "password")

答案 1 :(得分:0)

您可以使用os.popen,它已在2.6中移至subprocess但仍应存在于2.3的os模块中。将模式设置为'w'并使用close()获取返回值。

答案 2 :(得分:0)

还有另一个expect的Python实现,可以轻松支持pty。有一个包含ssh的库,可以使用它发送密码。它是Pycopia中的sshlib module。那里有一个处理密码的登录方法。它还使用了Pycopia的expect和process(proctools)模块。我最初是为Python 2.2编写的,所以它们可能适合你。但是,他们可能没有,因为我已经随着时间的推移自由使用了其他可能已经悄悄进入的新功能。

这些模块的主要目标是使处理子进程(如您所描述的)更容易,更“Pythonic”。