代码之家  ›  专栏  ›  技术社区  ›  David

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

  •  22
  • David  · 技术社区  · 14 年前

    我使用以下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], )
    
    5 回复  |  直到 8 年前
        1
  •  31
  •   Richard Hansen Bi Rico    10 年前

    您可以使用python的 -u 旗帜:

    -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 使用新的文件对象作为标准输入)。我说“应该”,因为这个地区 习惯于 在某些平台上有许多错误和问题(提供全面通用的跨平台是非常困难的功能)--我不确定它的状态是什么,但我绝对建议在所有感兴趣的平台上进行彻底的测试,以确保一切顺利进行。( -U 如果可以满足您的需求,那么完全删除缓冲区应该可以减少所有平台上的问题)。

        2
  •  22
  •   Søren Løvborg    11 年前

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

    import sys
    
    while True:
        line = sys.stdin.readline()
        if not line: break # EOF
    
        sys.stdout.write('> ' + line.upper())
    

    这使我可以使用Ubuntu13.04上的python 2.7.4和python 3.3.1进行行缓冲读取。

        3
  •  10
  •   Antti Haapala -- Слава Україні    10 年前

    这个 sys.stdin.__iter__ 仍然是行缓冲的,可以有一个行为基本相同的迭代器(在eof停止,而 stdin.__iter__ 不会使用 the 2-argument form of iter 使迭代器 sys.stdin.readline :

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

    或提供 None 作为哨兵(但请注意,然后你需要自己处理EOF条件)。

        4
  •  3
  •   Denilson Sá Maia    9 年前

    这在Python3.4.3中对我很有用:

    import os
    import sys
    
    unbuffered_stdin = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0)
    

    这个 documentation for fdopen() 说它只是 open() .

    open() 有一个可选的 buffering 参数:

    缓冲 是用于设置缓冲策略的可选整数。传递0以关闭缓冲(仅在二进制模式下允许),传递1以选择行缓冲(仅在文本模式下可用),传递1以指示固定大小块缓冲区的字节大小。

    换言之:

    • 完全无缓冲 STDIN要求 二元的 并将零作为缓冲区大小传递。
    • 行缓冲 要求 文本 模式。
    • 任何其他缓冲区大小似乎都适用于 二元的 文本 模式(根据文档)。
        5
  •  0
  •   Community CDub    8 年前

    我用python 2.7做这件事的唯一方法是:

    tty.setcbreak(sys.stdin.fileno())
    

    Python nonblocking console input . 这将完全禁用缓冲并抑制回声。

    编辑:关于Alex的答案,第一个建议(调用python -u )在我的情况下是不可能的(见 shebang limitation )

    第二个命题(用较小的缓冲区复制fd: os.fdopen(sys.stdin.fileno(), 'r', 100) )当我使用0或1的缓冲区时不工作,因为它是用于交互式输入的,我需要立即处理每个按下的字符。