9

I have a bunch of legacy code for encoding raw emails that contains a lot of print statements such as

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

This is all well and good for emails, but we're now leveraging the same code for outputting HTTP request. The problem is that the Python print statement outputs '\n' whilst HTTP requires '\r\n'.

It looks like Python (2.6.4 at least) generates a trailing PRINT_NEWLINE byte code for a print statement which is implemented as

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

Thus it appears there's no easy way to override the default newline behaviour of print. I have considered the following solutions

  • After writing the output simply do a .replace('\n', '\r\n'). This will interfere with HTTP messages that use multipart encoding.
  • Create a wrapper around the destination file object and proxy the .write method
  • def write(self, data):
        if data == '\n':
            data = '\r\n'
        return self._file.write(data)
    

  • Write a regular expression that translates print >>f, text to f.write(text + line_end) where line_end can be '\n' or '\r\n'.
  • I believe the third option would be the most appropriate. It would be interesting to hear what your Pythonic approach to the problem would be.

    4

    6 回答 6

    10

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

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

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

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

    于 2009-11-05T01:25:38.740 回答
    8

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

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

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

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

    于 2009-11-04T23:48:07.830 回答
    4

    In python2.x, I think you can do:

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

    to supress the trailing new line.

    In python3.x, it's a lot simpler:

    print("some msg", end = "\r\n", file = f)
    
    于 2009-11-05T00:45:44.747 回答
    0

    I think I would define a new function writeline in an inherited file/stream class and update the code to use writeline instead of print. The file object itself can hold the line ending style as a member. That should give you some flexibility in behavior and also make the code a little clearer i.e. f.writeline(text) as opposed to f.write(text+line_end).

    于 2009-11-05T00:37:29.820 回答
    0

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

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

    于 2009-11-05T01:15:51.100 回答
    0

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

    于 2009-11-05T10:34:18.177 回答