Python readline() из строки?

В python есть встроенный способ сделать readline() в строке? У меня большой объем данных и вы хотите удалить только первые пары строк без разделения split() на всю строку.

Гипотетический пример:

def handleMessage(msg):
   headerTo  = msg.readline()
   headerFrom= msg.readline()
   sendMessage(headerTo,headerFrom,msg)

msg = "Bob Smith\nJane Doe\nJane,\nPlease order more widgets\nThanks,\nBob\n"
handleMessage(msg)

Я хочу, чтобы это привело к:  sendMessage("Bob Smith", "Jane Doe", "Jane,\nPlease order...")

Я знаю, что было бы довольно легко написать класс, который делает это, но я ищу что-то встроенное, если это возможно.

EDIT: Python v2.7

Ответ 1

Python 2

Вы можете использовать StringIO:

>>> msg = "Bob Smith\nJane Doe\nJane,\nPlease order more widgets\nThanks,\nBob\n"
>>> msg
'Bob Smith\nJane Doe\nJane,\nPlease order more widgets\nThanks,\nBob\n'
>>> import StringIO
>>> buf = StringIO.StringIO(msg)
>>> buf.readline()
'Bob Smith\n'
>>> buf.readline()
'Jane Doe\n'

Обязательно используйте cStringIO, если производительность важна.

Python 3

Вы можете использовать io.StringIO:

>>> import io
>>> buf = io.StringIO(msg)
>>> buf.readline()
'Bob Smith\n'
>>> buf.readline()
'Jane Doe\n'
>>> len(buf.read())
44

Ответ 2

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

Если вы хотите, чтобы первые строки N были отделены, просто сделайте .split("\n", N).

>>> foo = "ABC\nDEF\nGHI\nJKL"
>>> foo.split("\n", 1)
['ABC', 'DEF\nGHI\nJKL']
>>> foo.split("\n", 2)
['ABC', 'DEF', 'GHI\nJKL']

Итак, для вашей функции:

def handleMessage(msg):
   headerTo, headerFrom, msg = msg.split("\n", 2)
   sendMessage(headerTo,headerFrom,msg)

или если вы действительно хотели получить фантазию:

# either...
def handleMessage(msg):
   sendMessage(*msg.split("\n", 2))

# or just...
handleMessage = lambda msg: sendMessage(*msg.split("\n", 2))

Ответ 3

Сделайте это так, как это делает StringIO:

i = self.buf.find('\n', self.pos)

Итак, это означает:

pos = msg.find("\n")
first_line = msg[:pos]
...

Кажется более элегантным, чем использование всего StringIO...