当前位置:  开发笔记 > 编程语言 > 正文

为sys.stdin设置较小的缓冲区大小?

如何解决《为sys.stdin设置较小的缓冲区大小?》经验,为你挑选了3个好方法。

我正在使用以下bash命令模式运行memcached:

memcached -vv 2>&1 | tee memkeywatch2010098.log 2>&1 | ~/bin/memtracer.py | tee memkeywatchCounts20100908.log

尝试跟踪无与伦比的获取到平台键的集合.

memtracer脚本位于下方并按预期工作,只有一个小问题.看到中间日志文件大小,memtracer.py在memkeywatchYMD.log大小约为15-18K之前不会开始输入.有没有更好的方法来读取stdin或者可能是将缓冲区大小降低到1k以下以获得更快的响应时间?

#!/usr/bin/python

import sys
from collections import defaultdict

if __name__ == "__main__":


    keys = defaultdict(int)
    GET = 1
    SET = 2
    CLIENT = 1
    SERVER = 2

    #if <
    for line in sys.stdin:
        key = None
        components = line.strip().split(" ")
        #newConn = components[0][1:3]
        direction = CLIENT if components[0].startswith("<") else SERVER

        #if lastConn != newConn:        
        #    lastConn = newConn

        if direction == CLIENT:            
            command = SET if components[1] == "set" else GET
            key = components[2]
            if command == SET:                
                keys[key] -= 1                                                                                    
        elif direction == SERVER:
            command = components[1]
            if command == "sending":
                key = components[3] 
                keys[key] += 1

        if key != None:
            print "%s:%s" % ( key, keys[key], )

Alex Martell.. 33

您可以使用python的-u标志从stdin/stdout中完全删除缓冲:

-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
         see man page for details on internal buffering relating to '-u'

并且手册页澄清了:

   -u     Force stdin, stdout and stderr to  be  totally  unbuffered.   On
          systems  where  it matters, also put stdin, stdout and stderr in
          binary mode.  Note that there is internal  buffering  in  xread-
          lines(),  readlines()  and  file-object  iterators ("for line in
          sys.stdin") which is not influenced by  this  option.   To  work
          around  this, you will want to use "sys.stdin.readline()" inside
          a "while 1:" loop.

除此之外,不支持更改现有文件的缓冲,但是您可以使用os.fdopen创建具有与现有文件相同的基础文件描述符的新文件对象,并可能使用不同的缓冲.也就是说,

import os
import sys
newin = os.fdopen(sys.stdin.fileno(), 'r', 100)

应该绑定newin到一个文件对象的名称,该文件对象读取与标准输入相同的FD,但一次只缓冲大约100个字节(并且您可以继续sys.stdin = newin使用新文件对象作为此处的标准输入).我说"应该",因为这个区域过去常常在某些平台上出现一些错误和问题(提供完全通用的跨平台功能非常困难) - 我不确定它现在的状态是什么,但是我d绝对建议在所有感兴趣的平台上进行全面测试,以确保一切顺利.(-u,完全删除缓冲,如果可能满足您的要求,应该在所有平台上使用更少的问题).



1> Alex Martell..:

您可以使用python的-u标志从stdin/stdout中完全删除缓冲:

-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)
         see man page for details on internal buffering relating to '-u'

并且手册页澄清了:

   -u     Force stdin, stdout and stderr to  be  totally  unbuffered.   On
          systems  where  it matters, also put stdin, stdout and stderr in
          binary mode.  Note that there is internal  buffering  in  xread-
          lines(),  readlines()  and  file-object  iterators ("for line in
          sys.stdin") which is not influenced by  this  option.   To  work
          around  this, you will want to use "sys.stdin.readline()" inside
          a "while 1:" loop.

除此之外,不支持更改现有文件的缓冲,但是您可以使用os.fdopen创建具有与现有文件相同的基础文件描述符的新文件对象,并可能使用不同的缓冲.也就是说,

import os
import sys
newin = os.fdopen(sys.stdin.fileno(), 'r', 100)

应该绑定newin到一个文件对象的名称,该文件对象读取与标准输入相同的FD,但一次只缓冲大约100个字节(并且您可以继续sys.stdin = newin使用新文件对象作为此处的标准输入).我说"应该",因为这个区域过去常常在某些平台上出现一些错误和问题(提供完全通用的跨平台功能非常困难) - 我不确定它现在的状态是什么,但是我d绝对建议在所有感兴趣的平台上进行全面测试,以确保一切顺利.(-u,完全删除缓冲,如果可能满足您的要求,应该在所有平台上使用更少的问题).


不幸的是,Python 3仍然顽固地在缓冲文本模式下打开`stdin`.现在只有`stdout`和`stderr`受到`-u`开关的影响.
这在Python 3.4.3中适用于我:`os.fdopen(sys.stdin.fileno(),'rb',buffering = 0)`

2> Søren Løvbor..:

你可以简单地使用sys.stdin.readline()而不是sys.stdin.__iter__():

import sys

while True:
    line = sys.stdin.readline()
    if not line: break # EOF

    sys.stdout.write('> ' + line.upper())

这使我在Ubuntu 13.04上使用Python 2.7.4和Python 3.3.1进行行缓冲读取.


这与问题无关,你的意思是将其作为评论.
我的理解,问题是"是否有更好的方法标准输入读" [在管道中使用Python脚本时,为了避免输入缓冲器问题]我的回答(三年制晚,因为它可能是)回答"是,使用`readline`而不是`__iter__`".但也许我的答案是依赖于平台的,如果你尝试上面的代码,你仍然有缓冲问题?
有趣的亚历克斯没有抓住这个,https://github.com/certik/python-2.7/blob/c360290c3c9e55fbd79d6ceacdfc7cd4f393c1eb/Objects/fileobject.c#L1377你说得对,读取线可能更快,因为它在file_internext缓冲区中逐步使用getc 8192如源中所定义.

3> Antti Haapal..:

sys.stdin.__iter__仍然行缓冲,一个可具有一个其行为大多相同的迭代器(停止在EOF,而stdin.__iter__不会)通过使用的2个参数的形式iter作出的一个迭代sys.stdin.readline:

import sys

for line in iter(sys.stdin.readline, ''):
    sys.stdout.write('> ' + line.upper())

或提供None哨兵(但请注意,您需要自己处理EOF条件).


作为对soren的回答的评论,这似乎会更好。Alex Martelli和Soren提供了答案,但更多的是Soren输入的改进。
推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有