python - 为什么我的函数在 IDLE 中比 python 的 print 函数更快?

标签 python python-3.x printing python-idle

我不久前写了这个函数:

def faster_print(*args, sep=" ", end="\n", file=stdout):
    file.write(sep.join(map(str, args))+end)

我测试了它:

from sys import stdout
from time import perf_counter

def faster_print(*args, sep=" ", end="\n", file=stdout):
    file.write(sep.join(map(str, args))+end)

def time(function, *args, **kwargs):
    start = perf_counter()
    function(*args, **kwargs)
    return perf_counter()-start

def using_normal_print(number):
    for i in range(number):
        print("Hello world.", 5, 5.0, ..., str)

def using_faster_print(number):
    for i in range(number):
        faster_print("Hello world.", 5, 5.0, ..., str)

normal_time = time(using_normal_print, number=100)
faster_time = time(using_faster_print, number=100)

print("Normal print:", normal_time)
print("My print function", faster_time)

事实证明,它只是在 IDLE 中更快,而不是在 cmd 中更快。我知道 IDLE 为 sys.stdout 、 sys.stdin 和 sys.stderr 创建自己的对象,但我不明白为什么它只减慢 python 内置 print 函数的速度。 This答案说内置的 print 函数是用 c 编写的。因为我的函数需要从 python 字节码编译成机器代码,这难道不应该使它更快吗?

我使用的是 Python 3.7.9 和 IDLE 版本 3.7.9

最佳答案

TheLizard,感谢您报告和修改您的实验。作为 IDLE 维护者,我关心 IDLE 速度。我注意到打印到屏幕有时比在 Python 终端/控制台 REPL 中慢得多。在后者中,Python 与屏幕窗口在同一进程中执行,并且 screen.write 直接写入屏幕缓冲区。另一方面,IDLE 在单独的进程中执行用户代码。在该过程中,替换 sys.stdout 通过套接字将输出发送到 IDLE GUI 进程,然后调用 tkinter text.insert,后者调用写入屏幕 bugger 的 tcl/tk 函数。但到目前为止,我还没有进行适当的调查。

我在我的 Win 10 机器上运行了 3.10.0a5 中的代码。在 REPL 中,正常和快速打印需要 0.05 秒。在 IDLE 中,它们花费了大约 1.1 和 0.3 秒。系数 6 (.3/.05) 由上面的开销解释。但附加系数约为 3.7 (1.1/.3)?

为了测试 kaya3 的第二个假设,我定义了 s = 'a'*75 并将打印参数替换为 s。在 REPL 中,时间仍然是 0.05 和 0.05。在 IDLE 中,它们约为 0.41 和 0.31。我的结论是,有一点内部打印功能开销,但 3.7 的大部分是额外的套接字到屏幕开销。当 print 写入缓冲区时,没有理由预先连接小字符串,因为多个 stdout.writes 本质上是在进行连接,无论是屏幕缓冲区还是磁盘缓冲区。

为了进一步测试这一点,我将测试更改为写入 3 个 block ,每 block 40 行。 REPL 时间保持不变。在 IDLE 中,它们的平均值约为 0.058 和 0.05,大约与 REPL 中一样快。

结论:我应该记录一下,如果在 IDLE 中定期运行而编写的代码进行打印并且关心速度,则应该首先将想要显示的所有内容预先组装到一个字符串中,然后只打印该字符串。 IDLE 为回溯执行此操作,这就是它们显示“一次全部”的原因。

关于python - 为什么我的函数在 IDLE 中比 python 的 print 函数更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66286367/

相关文章:

python-3.x - 向重写的函数添加额外的参数,而不会出现 pylint 提示

c# - 为 PDF 设置页边距、页眉和页脚而不重叠

java - 从 Java 打印 PDF 文档时,部分文本会旋转

python - 在 AWS 上使用 Spotipy 通过 Python 对 Spotify 进行用户身份验证

python - 如何让word2vec模型的加载时间和内存使用更加高效?

python - 如何在 PyCharm 中禁用添加相对路径?

python - 如何检索 Steam 市场价格历史?

python - 如何获取每个季度开始的 'Q'

python - Flask - 如何查询 BLOB 图像数据并将其显示在 HTML/Jinja2 上?

objective-c - 跳过 IOS 8 中的打印 UI?