覆盖Python的打印语句中换行符生成的行为

9

我有一堆编码原始电子邮件的旧代码,其中包含大量的打印语句,例如

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'
  • 我认为第三个选项可能是最合适的。很有趣听听您对该问题采用Python的方法。

    6个回答

    10

    现在,您应该通过定义一个新的输出函数来永久解决问题。 如果是print功能,这将更容易。

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

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

    一旦您替换了问题中的所有打印语句,您就不再有这个问题了--您可以始终更改函数的行为!这是Python 3中将print作为函数的一个重要原因--因为在Python 2.x中,“所有”项目都不可避免地经历所有打印语句不再灵活的阶段,并且没有简单的解决方法。


    8
    永久放弃使用print。把它视为调试工具,而不是生产代码的真正组成部分。 - S.Lott

    8
    (不确定这是否与您打算使用的包装器相符,但是以防万一...)
    在Python 2.6(以及许多前版本)中,您可以通过在print语句末尾添加逗号来抑制换行,例如:
    data = 'some msg\r\n'
    print data,  # note the comma
    

    使用这种方法的缺点是,在Python3中,打印语法和行为发生了变化。

    4
    在Python2.x中,我认为您可以这样做:
    print >>f "some msg\r\n",
    

    抑制行末换行符。

    在Python 3.x中,这变得简单了很多:

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

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

    0

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

    很遗憾,在Python 2.x中,print是一个语句,但在Python 3.x中,print可以被用户定义的某些内容重载。


    0

    Python有模块可以轻松处理电子邮件和HTTP头部。我建议您使用它们,而不是再次解决已经解决的问题。


    +1个好建议,Lennart。我们都在试图“利用现有代码”中“纵容”OP,但根据他/她的情况,你是正确的,我们应该始终记住这些“包含的电池”。 - mjv
    1
    我们实际上正在使用从stdlib电子邮件包中派生的类。例如,email.Generator(Python 2.4)大量使用print >>。这对于电子邮件非常好,只需要\n,但我们还将该代码用于解析、修改和重新生成HTTP请求(需要\r\n)。 - brotchie
    你正在使用电子邮件模块生成HTTP请求?难怪你会遇到问题。 - Lennart Regebro

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接