【问题标题】:The difference between sys.stdout.write and print?sys.stdout.write 和 print 的区别?
【发布时间】:2011-03-16 20:58:55
【问题描述】:

是否存在sys.stdout.write() 优于print 的情况?

示例:更好的性能;更有意义的代码)

【问题讨论】:

  • 哪个版本的 Python? 2.x 还是 3.x?
  • 老实说,我想知道两者,虽然我没有使用 Python 3 的经验。更新了问题。
  • @S.Lott :询问sys.stdout.write()print 之间的基本区别(和/或为什么Python 两者都有)是一个完全合理的问题,不需要示例。 OP 没有说命令语法令人困惑。

标签: python printing stdout


【解决方案1】:

在哪些情况下 sys.stdout.write() 更适合打印?

我发现在多线程情况下,stdout 比 print 效果更好。我使用队列 (FIFO) 来存储要打印的行,并在打印行之前保留所有线程,直到我的打印队列为空。即便如此,使用 print 我有时会在调试 I/O 上丢失最后的 \n(使用 Wing Pro IDE)。

当我在字符串中使用带有 \n 的 std.out 时,调试 I/O 格式正确并且 \n 被准确显示。

【讨论】:

  • 你知道为什么在这种情况下 stdout 应该比 print 工作得更好,或者这是轶事吗?您能否提供一个发生这种情况的最小工作示例?
  • 我的想法是标准输出的工作水平低于打印。我肯定有线程损坏,因为两个打印例程正在争夺通过标准输出。从每个线程写入一个标准输出为我消除了损坏。
【解决方案2】:

最好在动态打印有用的情况下,例如在较长的过程中提供信息:

import time, sys
Iterations = 555
for k in range(Iterations+1):

    # Some code to execute here ...

    percentage = k / Iterations
    time_msg = "\rRunning Progress at {0:.2%} ".format(percentage)
    sys.stdout.write(time_msg)
    sys.stdout.flush()
    time.sleep(0.01)

【讨论】:

  • print(time_msg, end='') 代替 sys.stdout.write(time_msg) sys.stdout.flush() 也有效
【解决方案3】:

在尝试将字节打印为其十六进制外观时,其中一个区别如下。例如,我们知道255的十进制值是十六进制的0xFF

val = '{:02x}'.format(255)

sys.stdout.write(val) # Prints ff2
print(val)            # Prints ff

【讨论】:

  • 这不是这个问题。它只会发生在交互式 shell 中,因为... write() 没有添加 \n 并返回(和交互式 shell 显示)函数的返回值(写入的字符数)、十六进制表示或任何其他正在显示的内容是无关紧要的.
【解决方案4】:

在 Python 2 中,如果需要传递函数,则可以将 os.sys.stdout.write 分配给变量。您不能使用 print 执行此操作(在 REPL 中)。

>import os
>>> cmd=os.sys.stdout.write
>>> cmd('hello')
hello>>>

按预期工作。

>>> cmd=print
  File "<stdin>", line 1
    cmd=print
            ^
SyntaxError: invalid syntax

那行不通。 print 是一个神奇的功能。

【讨论】:

    【解决方案5】:

    printsys.stdout.write 在 Python 3 中的区别也是在终端中执行时返回的值。在 Python 3 中,sys.stdout.write 返回字符串的长度,而 print 只返回 None

    因此,例如在终端中以交互方式运行以下代码将打印出字符串及其长度,因为在交互运行时会返回并输出长度:

    >>> sys.stdout.write(" hi ")
     hi 4
    

    【讨论】:

      【解决方案6】:
      >>> sys.stdout.write(1)
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: expected a string or other character buffer object
      >>> sys.stdout.write("a")
      a>>> sys.stdout.write("a") ; print(1)
      a1
      

      观察上面的例子:

      1. sys.stdout.write 不会写入非字符串对象,但print

      2. sys.stdout.write 不会在末尾添加换行符,但print

      如果我们深入潜水,

      sys.stdout 是一个文件对象,可用于 print() 的输出

      如果print()的文件参数未指定,则使用sys.stdout

      【讨论】:

        【解决方案7】:

        print 只是一个瘦包装器,用于格式化输入(可修改,但默认情况下,在 args 和换行符之间有一个空格)并调用给定对象的 write 函数。默认情况下,此对象为sys.stdout,但您可以使用“chevron”形式传递文件。例如:

        print >> open('file.txt', 'w'), 'Hello', 'World', 2+3
        

        见:https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


        在 Python 3.x 中,print 成为一个函数,但由于 file 参数,它仍然可以传递 sys.stdout 以外的其他内容。

        print('Hello', 'World', 2+3, file=open('file.txt', 'w'))
        

        https://docs.python.org/3/library/functions.html#print


        在 Python 2.6+ 中,print 仍然是一个语句,但它可以作为函数使用

        from __future__ import print_function
        

        更新:Bakuriu 评论指出 print 函数和 print 语句之间(更一般地说是函数和语句之间)存在细微差别。

        如果在评估参数时出错:

        print "something", 1/0, "other" #prints only something because 1/0 raise an Exception
        
        print("something", 1/0, "other") #doesn't print anything. The function is not called
        

        【讨论】:

        • 另外值得注意的是,print 还会在您编写的任何内容后附加一个换行符,而 sys.stdout.write 不会发生这种情况。
        • 如果您需要编写双版本代码(例如与 Python 2.x 和 Python 3.x 同时工作的代码),sys.stdout.write 也更通用。
        • @MichaelMior 您可以取消 print 附加一个尾随逗号的换行符:print "this",; print "on the same line as this"
        • sys.stdout.write() 也会缓冲输入,并且可能不会立即将输入刷新到 fd。为了确保它的行为类似于打印功能,您应该添加:sys.stdout.flush()
        • 您可以使用print(blah, end="") 来防止打印中出现换行符。
        【解决方案8】:

        print 首先将对象转换为字符串(如果它还不是字符串)。如果它不是行的开头和结尾的换行符,它也会在对象之前放置一个空格。

        使用stdout时,需要自己将对象转成字符串(比如调用“str”),并且没有换行符。

        所以

        print 99
        

        相当于:

        import sys
        sys.stdout.write(str(99) + '\n')
        

        【讨论】:

        • +1 用于提及换行符!这是print.write() 之间的主要区别,我想说。
        • 注意:print 可以省略换行符。在 Python 2.x 中,在末尾加一个逗号,会输出一个空格字符,但没有换行符。例如。 print 99, 在 Python 3 中,print(..., end='') 将避免添加换行符(也避免添加空格,除非您使用 end=' '
        • 这不是真的,print 操作在 python2.X 中的信号处理程序中的行为略有不同,即在示例中不能用 sys.stdout 替换 print:stackoverflow.com/questions/10777610/…
        • 为了获得更好的性能,假设print(99) 相当于:sys.stdout.write(str(99));sys.stdout.write('\n')
        【解决方案9】:

        在 Python 3 中,有正当理由使用 print over sys.stdout.write,但这个理由也可以变成使用 sys.stdout.write 的理由。

        这个原因是,现在 print 是 Python 3 中的一个函数,你可以覆盖它。因此,您可以在一个简单的脚本中随处使用 print,并决定那些打印语句需要写入 stderr。您现在可以重新定义打印功能,您甚至可以通过使用内置模块更改打印功能来全局更改它。当然,使用file.write,您可以指定文件是什么,但通过覆盖打印,您还可以重新定义行分隔符或参数分隔符。

        反之亦然。也许您绝对确定您写信给stdout,但也知道您要将打印更改为其他内容,您可以决定使用sys.stdout.write,并将打印用于错误日志或其他内容。

        因此,您使用什么取决于您打算如何使用它。 print 更灵活,但这可能是使用和不使用它的原因。我仍然会选择灵活性,并选择打印。使用print 的另一个原因是熟悉度。现在有更多人会知道您所说的印刷品是什么意思,而更少人知道sys.stdout.write

        【讨论】:

          【解决方案10】:

          在某些情况下 sys.stdout.write() 是否更可取 打印?

          例如,我正在开发一个小函数,它在将数字作为参数传递时以金字塔格式打印星星,尽管您可以使用 end="" 来完成此操作在单独的行中打印,我使用 sys.stdout.writeprint 配合来完成此操作工作。详细说明此 stdout.write 打印在同一行中,而 print 始终将其内容打印在单独的行中。

          import sys
          
          def printstars(count):
          
              if count >= 1:
                  i = 1
                  while (i <= count):
                      x=0
                      while(x<i):
                          sys.stdout.write('*')
                          x = x+1
                      print('')
                      i=i+1
          
          printstars(5)
          

          【讨论】:

            【解决方案11】:

            至少有一种情况需要sys.stdout 而不是打印。

            当你想覆盖一行而不转到下一行时,例如在绘制进度条或状态消息时,你需要循环类似的东西

            Note carriage return-> "\rMy Status Message: %s" % progress
            

            而且由于 print 添加了换行符,所以最好使用 sys.stdout

            【讨论】:

            • 如果 print 添加了一个新行,为什么不直接使用 print('message', end = '') 呢?
            【解决方案12】:

            以下是基于 Mark Lutz 的Learning Python一书的一些示例代码,可解决您的问题:

            import sys
            temp = sys.stdout                 # store original stdout object for later
            sys.stdout = open('log.txt', 'w') # redirect all prints to this log file
            print("testing123")               # nothing appears at interactive prompt
            print("another line")             # again nothing appears. it's written to log file instead
            sys.stdout.close()                # ordinary file object
            sys.stdout = temp                 # restore print commands to interactive prompt
            print("back to normal")           # this shows up in the interactive prompt
            

            在文本编辑器中打开 log.txt 将显示以下内容:

            testing123
            another line
            

            【讨论】:

            • 有什么办法可以让我打印到屏幕以及写入文件吗?
            • @DeveshSaini:是的,只需使用至少具有 write() 和 flush() 函数的代理类覆盖 sys.stdout。我写了一个例子 sn -p here.
            【解决方案13】:

            我的问题是在某些情况下sys.stdout.write()print 更可取

            如果您正在编写一个可以写入文件和标准输出的命令行应用程序,那么它很方便。您可以执行以下操作:

            def myfunc(outfile=None):
                if outfile is None:
                    out = sys.stdout
                else:
                    out = open(outfile, 'w')
                try:
                    # do some stuff
                    out.write(mytext + '\n')
                    # ...
                finally:
                    if outfile is not None:
                        out.close()
            

            这确实意味着您不能使用with open(outfile, 'w') as out: 模式,但有时它是值得的。

            【讨论】:

            • 严格来说,您可以使用with -- def process(output): # ... / if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)(当然,在必要时添加换行符)。不过,这绝对不是很干净,这是肯定的。
            【解决方案14】:

            我的问题是有没有 是这样的情况 sys.stdout.write() 最好 print

            前几天完成一个脚本的开发后,我把它上传到了一个unix服务器。我所有的调试消息都使用了print 语句,并且这些不会出现在服务器日志中。

            在这种情况下,您可能需要sys.stdout.write

            【讨论】:

            • 嗯?您确定这是print()sys.stdout.write() 之间的区别,而不是stdoutstderr 之间的区别吗?对于调试,您应该使用logging 模块,它将消息打印到stderr
            • 是的。使用nohup 并重定向到.out 文件也是如此。
            • 使用 sys.stdout.flush() 会有所帮助。
            • 如果你使用nohup,默认情况下所有写到stdoutstderr的都会重定向到nohup.out,不管你是使用print还是stdout.write
            • 这个答案是推测和误导/错误的,绝对不应该有 40 多个赞成票(在撰写本文时)。
            【解决方案15】:

            在 2.x 中,print 语句对您提供的内容进行预处理,将其转换为字符串,处理分隔符和换行符,并允许重定向到文件。 3.x 把它变成了一个函数,但它仍然有同样的职责。

            sys.stdout 是一个文件或类似文件,具有写入它的方法,这些方法采用字符串或沿着该行的东西。

            【讨论】:

              猜你喜欢
              • 2013-12-27
              • 1970-01-01
              • 1970-01-01
              • 2012-08-20
              • 2011-12-22
              • 1970-01-01
              • 2016-03-03
              • 2013-10-17
              相关资源
              最近更新 更多