Чтение ввода от читателя в python в строку

У меня есть функция в Python, которая использует «читатель» (надеюсь, это правильный термин). По сути, функция должна иметь возможность использовать файл, sys.stdin и т. д. Затем она должна прочитать все строки и сохранить их в строке.

В настоящее время мои вызовы функций выглядят примерно так:

   read_data (sys.stdin, sys.stdout)

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

а сама функция выглядит так:

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

Когда я запускаю код и вставляю ввод в консоль для проверки, он фактически может читать все строки, включая последнюю строку, но после этого он застревает в строке «line = readline()». Я не уверен, что я делаю неправильно, любая помощь будет принята с благодарностью. Спасибо


person Asad S. Malik    schedule 12.02.2014    source источник
comment
FWIW Я думаю, что термин, который вы ищете, это IO объект. по уткам, вы в основном ищете любой объект, который реализует readline   -  person kojiro    schedule 12.02.2014
comment
Если вы работаете в Windows, вам может потребоваться добавить and line != '\r\n'. Для простоты вы можете перефразировать if как if not line in ["", ...]:   -  person Laur Ivan    schedule 12.02.2014
comment
@LaurIvan Я бы предложил оставить обнаружение конца файла операционной системе, т.е. к библиотекам Python. Приведенное выше решение также перестанет читать входной файл, когда встретится пустая строка, т.е. не в EOF. Угадайте, если это то, что намеревался сделать OP.   -  person David Unric    schedule 12.02.2014


Ответы (5)


Файл необходимо открыть перед чтением, например:

f = open(reader, "r")
text = f.readline()

^ Кроме того, старайтесь не использовать зарезервированные ключевые слова, такие как "str"

person Rishi    schedule 12.02.2014
comment
Часть проблемы в том, что иногда fd уже открыт. - person kojiro; 12.02.2014
comment
Спасибо за подсказку о str (на самом деле я использую s, просто укажите str в вопросе). И да, проблема возникает, поскольку я вызываю функцию и с sys.stdin. - person Asad S. Malik; 12.02.2014

Я бы рекомендовал реструктурировать вашу программу следующим образом:

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)
person Jayanth Koushik    schedule 12.02.2014
comment
Отличается ли ''.join([line for line in in_stream]) от ''.join(in_stream.readlines())? (Я хочу сказать, что, насколько мне известно, все объекты, реализующие readline, также реализуют readlines.) - person kojiro; 12.02.2014
comment
@kojiro: ''.join(in_stream.readlines()) в основном in_stream.read(). с пониманием я могу убрать новые строки или что-то сделать со строками. - person Jayanth Koushik; 12.02.2014

В одном случае вы передаете дескриптор открытого файла sys.stdin. В другом вы передаете строку. Последнее не соответствует вашему интерфейсу с методом readline. Вы можете исправить это одним из нескольких способов. Проверьте, есть ли у объекта метод readline:

if not hasattr(reader, "readline"): # and is callable, etc, etc
    reader = open(reader, 'r')

попробовать / кроме

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

Есть и другие способы. Вы должны задокументировать, что сама функция ожидает объект ввода-вывода, если это так.

person kojiro    schedule 12.02.2014

Вы обрабатываете строку как файловый объект (или любой объект, который имеет метод readline). Если вы хотите иметь возможность передавать как строки, так и файловые объекты, вы можете просто сначала проверить, является ли аргумент строкой.

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

Вы также можете использовать hasattr, чтобы проверить, имеет ли переданный объект метод readline, прежде чем решить, открывать ли его как файл.

person ebarr    schedule 12.02.2014

Если я правильно понимаю ваш вопрос, вам нужно поместить EndOfFile в поток. Для интерактивного ввода в Unix/Linux используйте Ctrl-d (т.е. ^d), в Windows Ctrl-z.

Без этого readline не возвращает пустую строку, как вы ожидаете.

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.
person David Unric    schedule 12.02.2014