7

I'm starting on a Python project in which stdin redirection is necessary, using code similar to below:

import sys
import StringIO

s = StringIO.StringIO("Hello")
sys.stdin = s
a = raw_input("Type something: ")
sys.stdin = sys.__stdin__
print("You typed in: "+a)

The problem is, after the code runs, the following is displayed:

Type something: You typed in: Hello

Is there a way to modify my code such that the following is displayed instead?

Type something: Hello

You typed in: Hello

I've been searching high and low but have found no answer yet. I'll really appreciate if anyone has an idea. Thanks!

4
  • 3
    "stdin redirection is necessary"? Really? That seems like an impossible situation. Why not replace raw_input with a callable object that does what you want? Commented Apr 28, 2011 at 0:43
  • I understand this is not a common situation, but it is really necessary. The code above is just a very simple example; in reality I need to run other people's code that asks for input, so I can't change the way they code their programs. Commented Apr 28, 2011 at 2:18
  • You don't change their code. You redefine a built-in function with your own version, import their code, and run their code using your version of the built-in. Commented Apr 28, 2011 at 2:20
  • Oh I see what you mean. However, I still can't think of an implementation using your idea that would be satisfactory yet. Would you mind posting a sample piece of code that might help me get closer to the solution? Thanks a lot! Commented Apr 28, 2011 at 2:26

3 Answers 3

4

Do this.

class MyRawInputFakeOutObject( object ):
    def __init__( self, the_fake_out_input_text ):
        self.input= the_fake_out_input_text
    def __call__( self, prompt ):
        print( prompt )
        return self.input

raw_input= MyRawInputFakeOutObject( "Hello" )

import some_existing_module

some_existing_module.the_existing_main()

Now the existing module is working with your raw_input, not the built-in raw_input. Yours can do anything to provide fake inputs and fake outputs.

Sign up to request clarification or add additional context in comments.

5 Comments

great answer! however, i find ian b's code to be a little bit easier to work with. Both should solve my problem though. Thanks a lot!
Would this method work for code that was not broken up into modules? For example, if one was given a script that had no functions or main defined wouldn't the import command just run the script (ie before raw_input is redefined)? Just a thought.
@Adam Lewis: Every Python file is a module. By definition. You cannot avoid breaking Python up into modules. When you have a "script" it's a module. Importing it will run it. While your comment has a lot of confusion in it, it does point up a change that's needed to handle those really poorly-written scripts with no if __name__=="__main__": section.
Point taken about the module comment. Your change addressed what I was trying to convey. I only brought it up because I can see a teacher's assistant grading a python assignment in this way. That said, if it is to grade a homework assignment I doubt well-written code is normal. Thanks for the clarification!
actually adam you just described my exact situation (I'm an assistant writing a program to automatically check students' answers) :) That's why I can't change part of the code myself. Thanks again everyone!
3

I'm not sure why you would need to, but you could always do this:

a = raw_input("Type something: ")
if sys.stdin is not sys.__stdin__:
    print(a)
print("You typed in: "+a)

Then again, swapping raw_input for your own implementation as needed would probably make more sense.

Edit: okay, based on your, comment it looks like you'll want to do some monkey patching. Something like this:

old_raw_input = raw_input

def new_raw_input(prompt):
    result = old_raw_input(prompt)
    if sys.stdin is not sys.__stdin__:
        print result
    return result

raw_input = new_raw_input

Of course, this might make the point of redirecting stdin moot.

4 Comments

Thanks for your answer! However, that's not what I need. I'm trying to run other people's codes that ask for input, so I can't change the way their programs are written.
Sounds like you should monkey patch the raw_input to your own implementation.
This is exactly what I want! Thanks a lot! I never knew we can do this crazy monkey patch thing with Python :)
If you're using 3.x this is useful.
1

EDIT: After reading the other answers and comments I think I have found a good way to really redirect the stdin. Note that I have assumed that you will know the the inputs to the end user's raw_inputs need to be.

User's Code (Named some_module.py)

print "running some module with 5 raw_input requests"
for x in range(5):
    value = raw_input("This is someone else's code asking its (" + str(x) + ") raw_input: ")
    print 'stdin value: ' + value

Your Test Script (Named whatever you like)

    import sys
    class MY_STD_IN( object ):
        def __init__(self, response_list):
            self.std_in_list = response_list
            self.std_in_length = len(response_list)
            self.index = 0

        def readline(self):
            value = self.std_in_list[self.index]      
            print value
            if self.index < self.std_in_length -1:
                self.index += 1
            else:
                self.index = 0

            return value

    predetermined_stdin_responses = ['Value 1\r', 'Value 2\r', 'Value 3\r']
    sys.stdin = MY_STD_IN( predetermined_stdin_responses )

    import some_module

Running the Script Yields

running some module with 5 raw_input requests
This is someone else's code asking its (0) raw_input: Value 1
stdin value: Value 1
This is someone else's code asking its (1) raw_input: Value 2
stdin value: Value 2
This is someone else's code asking its (2) raw_input: Value 3
stdin value: Value 3
This is someone else's code asking its (3) raw_input: Value 1
stdin value: Value 1
This is someone else's code asking its (4) raw_input: Value 2
stdin value: Value 2

Original Answer

Not sure if you're looking for such a literal answer but here it is

import sys
import StringIO

s = StringIO.StringIO("Hello")
sys.stdin = s
a = raw_input("Type something: ")
sys.stdin = sys.__stdin__
print(a+"\nYou typed in: "+a)

Yields:

Type something: Hello

You typed in: Hello

3 Comments

Thanks for your answer, but it's not what I need. I have to run other people's codes, so I can't change the way they code their programs. All I can do (that I know of) is to somehow manipulate stdin and stdout
Would you mind giving more of an example of what their code is and how you intend to interact with it? Meaning are you wanting to control the raw_input() of their program with your own data?
Yes, that's correct. I need to check a student's answer by feeding data into their function (either by providing an argument or through stdin) and then compare the stdout to a provided answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.