覆盖Python的print语句的换行符生成行为

时间:2009-11-04 23:36:17

标签: python printing cpython

我有一堆用于编码原始电子邮件的遗留代码,其中包含许多打印语句,例如

print >>f, "Content-Type: text/plain"

这对电子邮件来说都很好,但我们现在正在利用相同的代码来输出HTTP请求。问题是Python print语句输出'\n',而HTTP需要'\r\n'

看起来Python(至少2.6.4)为print语句生成一个尾随的PRINT_NEWLINE字节代码,该代码实现为

ceval.c:1582: err = PyFile_WriteString("\n", w);

因此,似乎没有简单的方法来覆盖print的默认换行行为。我考虑过以下解决方案

  • 写完输出后,只需执行.replace('\n', '\r\n')。这将干扰使用多部分编码的HTTP消息。
  • 围绕目标文件对象创建一个包装器并代理.write方法
  • def write(self, data):
        if data == '\n':
            data = '\r\n'
        return self._file.write(data)
    

  • 编写一个正则表达式,将print >>f, text翻译为f.write(text + line_end),其中line_end可以是'\n''\r\n'
  • 我认为第三种选择是最合适的。听听Pythonic解决问题的方法会很有趣。

    6 个答案:

    答案 0 :(得分:10)

    您应该立即通过定义新的输出函数来解决您的问题。打印一个函数,这会更容易。

    我建议编写一个新的输出函数,尽可能多地模仿现代打印函数签名(因为重用好的接口很好),例如:

    def output(*items, end="\n", file=sys.stdout):
        pass
    

    一旦您更换了所有相关的打印件,您就不再有这个问题 - 您可以随时更改功能的行为!这就是为什么print在Python 3中成为一个函数的一个重要原因 - 因为在Python 2.x中,“所有”项目总是经历所有print语句不再灵活的阶段,并且没有简单的出路。

    答案 1 :(得分:8)

    (不确定如何/如果这适合您打算使用的包装,但以防万一...)

    在Python 2.6(以及许多前面的版本)中,您可以通过在print语句的末尾添加逗号来禁止换行,如:

    data = 'some msg\r\n'
    print data,  # note the comma
    

    然而,使用这种方法的缺点是在Python3中更改了打印语法和行为。

    答案 2 :(得分:4)

    在python2.x中,我认为你可以这样做:

    print >>f "some msg\r\n",
    

    禁止尾随新行。

    在python3.x中,它更简单:

    print("some msg", end = "\r\n", file = f)
    

    答案 3 :(得分:0)

    我想我会在继承的文件/流类中定义一个新函数writeline,并更新代码以使用writeline而不是print。文件对象本身可以将行结束样式保存为成员。这应该会给你一些行为上的灵活性,并使代码更清晰,即f.writeline(text)而不是f.write(text+line_end)

    答案 4 :(得分:0)

    我也更喜欢你的第三个解决方案,但不需要使用f.write,任何用户编写的函数/ callable都可以。因此,接下来的变化将变得容易。如果您使用对象,您甚至可以隐藏其中的目标文件,从而删除一些语法噪音,如文件或换行符。

    太糟糕的打印是python 2.x中的一个语句,python 3.x打印可能只是被用户定义的内容重载。

    答案 5 :(得分:0)

    Python具有以简单易懂的方式处理电子邮件和http标头的模块。我建议你使用它们而不是再次解决已经解决的问题。