Вы делаете
printf ("Hi %s,</br />", $name);
перед установкой файлов cookie, что запрещено. Вы не можете отправить какой-либо вывод перед заголовками, даже пустую строку.
Monkeypatching print
is выполнимо, но это не очень хорошая идея. Во-первых, что вы хотите, если кто-то делает print(spam, eggs)
? Или print(spam, end='')
? Или print(spam, file=outfile)
?
Лучшее решение, вероятно, заменит sys.stdout
на обертку.
Обычный sys.stdout
- это простой старый текстовый файловый объект, TextIOWrapper
, как и те, которые вы получаете из open
, за исключением того, что когда вы пишете на него, он переходит на консоль вместо файла на диск.
И вы можете заменить его на что-либо еще, что соответствует протоколу TextIOBase
.
И писать TextIOBase
действительно просто. Все, что вам действительно нужно реализовать, это write
и / или read
и readline
(в зависимости от того, будете ли вы выводить вывод, ввод или оба), и все, что нужно сделать нашей оболочке в write
, - это буфер (f16) и передать их реальному файловому объекту внизу.
Как это:
import io
import sys
import textwrap
class Filler(io.TextIOBase):
def __init__(self, file, width=70):
self.file = file
self.textwrapper = textwrap.TextWrapper(width=width)
self.buf = ''
def write(self, buf):
self.buf += buf
lines = self.buf.split('\n')
self.buf = lines.pop()
for line in lines:
self.file.write(self.textwrapper.fill(line) + '\n')
def close(self):
if self.buf:
self.file.write(self.textwrapper.fill(buf))
self.buf = ''
self.file.close()
sys.stdout = Filler(sys.stdout, 32)
print('Spam spam spam spammity ' * 10)
print('Spam', 'Eggs')
sys.stdout.textwrapper.width = 72
print('Spam ' + 'spam ' * 50, 'and eggs', sep='... ')
print('Spam', end=' ')
print('Eggs', end=' ')
print('Cheese')
Технически я думаю, что я могу обманывать здесь несколько способов:
TextIOBase
хочет detach
, read
и readline
, даже если они здесь не имеют смысла. Но ABC, похоже, не применяет их как абстрактные методы, поэтому я не беспокоился. encoding
и errors
установлен на None
, так как мы просто переходим к другому TextIOBase
и ожидаем, что он сделает кодировку, но я не могу найти ничего, что говорит , что это законно. И если какой-то код должен был проверить sys.stdout.encoding
, чтобы увидеть, является ли это UTF-8 или что-то еще, это может быть проблемой. newlines
. Кроме того, пересылка других методов в self.file
может быть хорошей идеей, например fileno()
и isatty()
. Но я бы не стал беспокоиться о том, что любое приложение, которое хочет получить доступ к stdout
как TTY, возможно, должно знать о Filler
, которое мы застряли перед ним, а не просто прозрачно пройти через него.
sys.stdout
является file
, а не TextIOWrapper
. API, который нужно обернуть, немного отличается и не так точно определен. __future__
не используете функцию print
в стиле 3.x, print
является инструкцией, поэтому вы не можете обезвредить ее. (Я имею в виду, что вы могли бы написать крюк импорта, который байт-код взломал каждый байт-код PRINT_*
, или, может быть, даже ввел .so, который заменяет PyObject_Print
... но кто все равно заботится? Это Python 2.)
textwrap.TextWrapper
и вызвать его метод.fill
. Функция удобстваtextwrap.fill
создает новый экземпляр для каждого вызова. – PM 2Ring 13 July 2018 в 08:53@property
вFiller
, либо явно установитьstdout.textwrapper.width
, и теперь, когда я думаю об этом, это не так много недостаток. – abarnert 14 July 2018 в 02:31__init__
может легко принять всеTextwrap
kwargs и передать их. Конечно, OP может не нуждаться в такой гибкости. Говоря об этом, было бы неплохо получить некоторые отзывы от OP ... – PM 2Ring 14 July 2018 в 05:22