【问题标题】:Overriding the newline generation behaviour of Python's print statement覆盖 Python 的 print 语句的换行生成行为
【发布时间】:2009-11-04 23:36:17
【问题描述】:

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

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);

因此,似乎没有简单的方法可以覆盖 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 方法会很有趣。

    【问题讨论】:

      标签: python printing cpython


      【解决方案1】:

      您应该通过定义一个新的输出函数来解决您现在和永远的问题。如果是 print 一个函数,这会容易得多。

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

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

      一旦你替换了所有有问题的打印,你就不再有这个问题了——你总是可以改变你的函数的行为!这就是为什么在 Python 3 中 print 成为一个函数的一个重要原因——因为在 Python 2.x 中,“所有”项目总是会经历所有 print 语句不再灵活的阶段,并且没有简单的方法出去。

      【讨论】:

      • +1:永久放弃print。将其视为调试工具,而不是生产代码的真实部分。
      【解决方案2】:

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

      在 Python 2.6(和许多之前的版本)中,您可以通过在 print 语句的末尾添加一个逗号来取消换行,如下所示:

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

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

      【讨论】:

        【解决方案3】:

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

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

        抑制尾随的新行。

        在python3.x中,就简单多了:

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

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

            太糟糕的 print 是 python 2.x 中的一个语句,在 python 3.x 中 print 可以简单地被用户定义的东西重载。

            【讨论】:

              【解决方案6】:

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

              【讨论】:

              • +1 好建议,Lennart。我们都“幽默”了 OP,试图“利用现有代码”,但根据他/她的情况,你是对的,我们应该永远记住这些 "included batteries"
              • 我们实际上使用的是从 stdlib 电子邮件包中派生的类。例如 email.Generator (Python 2.4) 大量使用 print >>。这对电子邮件来说很好(只需要 \n),但我们也使用代码来解析、修改和重新生成 HTTP 请求(需要 \r\n)。
              • 您正在使用电子邮件模块生成http请求?难怪你会遇到问题。
              猜你喜欢
              • 2023-03-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-10-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多