重写Python打印语句的换行行为

9 投票
6 回答
7339 浏览
提问于 2025-04-15 15:40

我有一堆老旧的代码,用来处理原始邮件的编码,这些代码里有很多打印语句,比如:

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

这对于邮件来说没问题,但我们现在也想用这段代码来输出HTTP请求。问题是,Python的打印语句输出的是'\n',而HTTP需要的是'\r\n'

看起来Python(至少是2.6.4版本)在打印语句后会生成一个额外的PRINT_NEWLINE字节码,具体实现是:

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

所以,似乎没有简单的方法可以改变打印的默认换行行为。我考虑了以下几种解决方案:

  • 在输出后直接用.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 个回答

    4

    在python2.x中,我觉得你可以这样做:

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

    这样可以去掉最后的换行符。

    在python3.x中,这个过程简单多了:

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

    (不确定这是否适合你打算使用的包装器,但以防万一……)

    在Python 2.6(以及许多之前的版本)中,你可以通过在print语句的末尾加一个逗号来抑制换行,比如这样:

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

    不过,使用这种方法的缺点是,Python 3中的print语法和行为发生了变化。

    10

    你现在可以通过定义一个新的输出函数来解决你的问题,这样就能永远解决了。如果是用打印函数的话,这会简单很多。

    我建议你写一个新的输出函数,尽量模仿现代打印函数的样子(因为重用一个好的接口是很有帮助的),比如:

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

    一旦你把所有需要的打印都替换成这个新的函数,你就不再有这个问题了——你可以随时改变这个函数的行为!这就是为什么在Python 3中把打印做成一个函数的一个重要原因——因为在Python 2.x中,所有项目都会经历一个阶段,所有的print语句都变得不灵活,而没有简单的解决办法。

    撰写回答