Строка представления Python с реальными новыми строками

Я хочу использовать repr(), чтобы получить строковый литерал в кодировке Python (который я могу вставить в какой-нибудь исходный код), но я бы предпочел строку в тройных кавычках с реальными символами новой строки, а не escape-последовательность \n.

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

Какой самый простой способ сделать это?


Пример ввода:

foo????
bar

Или как строку Python:

'foo????\nbar'

Желаемый результат:

'''foo\xf0\x9f\x92\xa9
bar'''

Тройные одинарные или тройные двойные кавычки — это нормально, но я хочу, чтобы они разбивались на несколько строк.


Что у меня есть до сих пор:

#!/usr/bin/env python
import sys
import re

with open(sys.argv[1], 'r+') as f:
    data = f.read()
    f.seek(0)
    out = "''" + re.sub(r"\\n", '\n', repr(data)) + "''"
    f.write(out)
    f.truncate()

Я все еще пытаюсь понять регулярное выражение, чтобы избежать преобразования экранированных \n.

Цель состоит в том, что если я вставлю это обратно в исходный файл Python, я получу точно то же самое, что я прочитал.


Я использую Python 2.7.14.


person mpen    schedule 28.03.2019    source источник
comment
Разве это не просто print(your_string)? Я действительно не получаю желаемого ввода и вывода.   -  person wim    schedule 29.03.2019
comment
@wim № repr будет экранировать кавычки, смайлики и другие управляющие символы, которые мне нужны.   -  person mpen    schedule 29.03.2019
comment
Хорошо, опубликуйте пример ввода и вывода. Кстати, repr не будет избегать смайликов в текущей версии Python — может быть, вам следует пометить это с помощью python-2.x?   -  person wim    schedule 29.03.2019
comment
@wim Добавлено в вопрос.   -  person mpen    schedule 29.03.2019
comment
Вы действительно уверены, что хотите 'foo????\nbar', а не u'foo????\nbar'? Правильным выходом здесь будет foo\U0001f4a9\nbar - то, что вы здесь показываете, закодировано в кодировке utf-8.   -  person wim    schedule 29.03.2019
comment
Э-э... да, я думаю, ты прав. На самом деле в моем источнике нет смайликов, но могут быть какие-то другие странные вещи. В основном мне просто нужно, чтобы Python мог анализировать его и выводить так же, как ввод.   -  person mpen    schedule 29.03.2019


Ответы (2)


Как насчет splitlines и кодирования каждой строки отдельно:

s = 'foo????\nbar'

r = "'''" + '\n'.join(repr(x)[1:-1] for x in s.splitlines()) + "'''"

assert eval(r) == s

Если вы используете python2 и входные данные имеют юникод, то repr[2:-1] также удаляет начальный u. То же самое относится к входам py3 и bytes.

person georg    schedule 28.03.2019
comment
Умная. Разделите строки перед вызовом repr, чтобы избежать всей проблемы с экранированием. - person mpen; 29.03.2019

Окончательное решение для преобразования текстового файла в строку, которую вы можете вставить в исходный код:

#!/usr/bin/env python
import sys
import re
import io

with io.open(sys.argv[1], 'r+', encoding='utf8') as f:
    data = f.read()
    f.seek(0)
    out = u"u'''" + u'\n'.join(repr(x)[2:-1] for x in data.splitlines()) + u"'''"
    f.write(out)
    f.truncate()

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

Кредит:

person mpen    schedule 28.03.2019