Python StringIO - 有选择地将数据放入stdin

时间:2012-11-20 19:28:41

标签: python stdin stringio

我们正在使用一些我们没有源代码的编译python代码。代码提示用户输入,我们正在尝试自动化该部分。

基本上要求用户名,密码,然后根据某些情况提出一些不同的问题。我不知道编译的函数是使用raw_input,input还是其他东西。

我已经能够使用StringIO来替换带有用户名和密码的stdin,我可以用我自己的类替换stdout并找出即将出现的提示,但是在选择性地放置数据时我很难过根据我从stdout读到的东西进入stdin。

import sys
import re
from StringIO import StringIO

def test():
    overwrite = raw_input("The file exists, overwrite? ")
    notify = raw_input("This file is marked for notifies.  Notify?")
    sys.stdout.write("Overwrite: %s, Notify: %s" % (overwrite,notify))

class Catcher(object):
    def __init__(self):
        pass

    def write(self, msg):
        if re.search("The file exists, overwrite", msg):
            # put data into stdin 
        if re.search("The file is marked for notification", msg):
            # put data into stdin

sys.stdout = Catcher()
test()

我不能只预加载一个StringIO对象,因为问题可能因环境而异,但我需要自动输入stdin,因为他们试图把它放到一个自动构建系统中,所以他们会通过命令行提供默认值来回答发生的任何问题。

如果我在调用编译函数之前将stdin设置为一个空的StringIO对象,那么它只是错误输出EOF - 不知道如何让它等待输入。

这样的事情:

import sys
import re
from StringIO import StringIO

def test():
    overwrite = raw_input("The file exists, overwrite? ")
    notify = raw_input("This file is marked for notifies.  Notify?")
    sys.__stdout__.write("Overwrite: %s, Notify: %s" % (overwrite,notify))

class Catcher(object):
    def __init__(self, stdin):
        self.stdin = stdin

    def write(self, msg):
        if re.search("The file exists, overwrite", msg):
            self.stdin.write('yes\n')
        if re.search("The file is marked for notification", msg):
            self.stdin.write('no\n')

sys.stdin = StringIO()
sys.stdout = Catcher(sys.stdin)
test()

产地:

Traceback (most recent call last):
  File "./teststdin.py", line 25, in <module>
    test()
  File "./teststdin.py", line 8, in test
    overwrite = raw_input("The file exists, overwrite? ")
EOFError: EOF when reading a line

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

如果你想从你刚写过的StringIO中读取,你必须先将它倒回到你开始写作的位置。
此外,您的第二次搜索测试错误的字符串。

这应该有效:

import sys
import re
from StringIO import StringIO

def test():
    overwrite = raw_input("The file exists, overwrite? ")
    notify = raw_input("This file is marked for notifies.  Notify?")
    sys.__stdout__.write("Overwrite: %s, Notify: %s" % (overwrite,notify))

class Catcher(object):
    def __init__(self, stdin):
        self.stdin = stdin

    def write(self, msg):
        if re.search("The file exists, overwrite?", msg):
            self.stdin.truncate(0)
            self.stdin.write('yes\n')
            self.stdin.seek(0)
        if re.search("This file is marked for notifies.  Notify?", msg):
            self.stdin.truncate(0)
            self.stdin.write('no\n')
            self.stdin.seek(0)

sys.stdin = StringIO()
sys.stdout = Catcher(sys.stdin)
test()

答案 1 :(得分:0)

这是一个完全避免StringIO的解决方案:

import sys
import re

class Catcher(object):
    def __init__(self, handler):
        self.handler = handler
        self.inputs = []

    def __enter__(self):
        self.__stdin  = sys.stdin
        self.__stdout = sys.stdout
        sys.stdin = self
        sys.stdout = self

    def __exit__(self, type, value, traceback):
        sys.stdin  = self.__stdin
        sys.stdout = self.__stdout

    def write(self, value):
        result = self.handler(value)
        if result:
            self.inputs = [result] + self.inputs

    def readline(self):
        return self.inputs.pop()

用作:

def test():
    overwrite = raw_input("The file exists, overwrite? ")
    notify = raw_input("This file is marked for notifies.  Notify?")
    sys.__stdout__.write("Overwrite: %s, Notify: %s" % (overwrite,notify))


@Catcher
def exist_notify(msg):
    if re.search("The file exists, overwrite", msg):
        return 'yes'
    if re.search("This file is marked for notifies", msg):
        return 'no'

with exist_notify:
    test()