Q: Reading input from reader in python into string I have a function in Python which takes in a "reader" (I hope that's the right term). Basically the function should be able to use a file, sys.stdin etc. It then has to read all the lines and store them intro a string.
Currently my function calls look something like:
   read_data (sys.stdin, sys.stdout)

   read_data ("file.txt", "fileout.txt")

and the function itself looks like:
def read_data (reader, s) :

   str = ""

   str = r.readline()
   line = str
   while line != "" and line != None and line != '\n':
       line = r.readline()
       str = str + line

When I run the code and paste the input into the console to test, it actually is able to read all lines including the last line but after that it gets stuck in the "line = readline()". I'm not sure what I'm doing wrong, any help would be greatly appreciated. Thank you 

A: The file needs to be opened first before reading, e.g.:
f = open(reader, "r")
text = f.readline()

^ Also, try not to use reserved keywords like "str"

A: I would recommend restructuring your program like this:
def read_data(in_stream=sys.stdin, out_stream=sys.stdout):
    """
    in_srteam: stream open for reading (defaults to stdin)
    out_stream: stream open for writing (defaults to stdout)
    """

    s = ''.join([line for line in in_stream])
    out_stream.write(s)


A: In one case you're passing an open file descriptor sys.stdin. In another, you're passing a string. The latter doesn't match your interface of having a readline method. You can fix this one of several ways. Test if the object has a readline method:
if not hasattr(reader, "readline"): # and is callable, etc, etc
    reader = open(reader, 'r')

try/except
try:
    result = reader.readline()
except AttributeError:
    with open(reader,'r') as realreader:
        result = realreader.readline()

There are other ways, as well. You should document that the function itself expects an IO object, if that is the case.

A: You are treating a string like a file object (or any object which has a readline method). If you want to be able to pass both strings and file objects then you can just test to see if the argument is a string first. 
def read_data (reader, s) :
   if isinstance(reader,str):
       reader = open(reader,"r")   
   if isinstance(s,str):
       s = open(s,"w+")

   str = "" #avoid using str for a variable name

   str = r.readline()
   line = str
   while line != "" and line != None and line != '\n':
       line = r.readline()
       str = str + line

You could also use hasattr to test if the passed object has a readline method before choosing whether to try and open it as a file.

A: If I do understand your question correctly, you need to put EndOfFile into the stream. For interactive input in Unix/Linux use Ctrl-d (ie. ^d), in Windows Ctrl-z.
Without this readline does not return an empty string as you are expecting.
readline(...)
    readline([size]) -> next line from the file, as a string.

    Retain newline.  A non-negative size argument limits the maximum
    number of bytes to return (an incomplete line may be returned then).
    Return an empty string at EOF.

