2

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

3
  • FWIW I think the term you're looking for is IO object. Duck-wise, you're basically looking for any object that implements readline Commented Feb 12, 2014 at 13:50
  • If you're on windows you may need to add and line != '\r\n'. To keep things simpler you may want to rephrase the if as if not line in ["", ...]: Commented Feb 12, 2014 at 13:54
  • @LaurIvan I'd suggest to leave detection of end of file to an operating system, ie. to python libraries. Above solution would also stop reading an input file also when an empty line is met, ie. not at EOF. Guess if that's what OP did intended. Commented Feb 12, 2014 at 14:25

5 Answers 5

1

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"

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

2 Comments

Part of the problem is that sometimes the fd is already open.
Thanks for the tip about str (I'm actually using s, just put str in the question). And yes, the problem arises since I call the function with sys.stdin as well.
1

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)

2 Comments

Is ''.join([line for line in in_stream]) different from ''.join(in_stream.readlines())? (My point being that to my knowledge, all objects that implement readline also implement readlines.)
@kojiro: ''.join(in_stream.readlines()) is basically in_stream.read(). with the comprehension, I can strip the newlines or do something to the lines.
0

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.

Comments

0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.