Python 是否为sys.stdin设置较小的缓冲区大小?
我使用以下bash命令模式运行memcached:Python 是否为sys.stdin设置较小的缓冲区大小?,python,stdin,buffering,Python,Stdin,Buffering,我使用以下bash命令模式运行memcached: memcached -vv 2>&1 | tee memkeywatch2010098.log 2>&1 | ~/bin/memtracer.py | tee memkeywatchCounts20100908.log 尝试跟踪平台范围内密钥的不匹配获取集 memtracer脚本如下所示,可以根据需要工作,但有一个小问题。查看中间日志文件大小,memtracer.py直到memkeywatchYMD.log才开始获
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], )
#/usr/bin/python
导入系统
从集合导入defaultdict
如果名称=“\uuuuu main\uuuuuuuu”:
keys=defaultdict(int)
GET=1
集合=2
客户端=1
服务器=2
#如果<
对于sys.stdin中的行:
键=无
components=line.strip().split(“”)
#newConn=组件[0][1:3]
direction=CLIENT if components[0]。startswith(“您可以使用python的-u
标志从stdin/stdout中完全删除缓冲:
-u:无缓冲二进制stdout和stderr(也叫pythonunbuffer=x)
有关'-u'的内部缓冲的详细信息,请参见手册页
手册页澄清了:
-u强制标准输入、标准输出和标准输出完全无缓冲。打开
重要的系统还包括stdin、stdout和stderr
二进制模式。请注意,xread中有内部缓冲-
lines()、readlines()和文件对象迭代器(“用于
sys.stdin”),不受此选项的影响。要正常工作
在这方面,您需要在内部使用“sys.stdin.readline()”
一个“while1:”循环。
除此之外,不支持更改现有文件的缓冲区,但您可以使用与现有文件具有相同底层文件描述符的新文件对象,以及可能不同的缓冲区,例如
应该将newin
绑定到一个文件对象的名称,该文件对象读取与标准输入相同的FD,但一次只能缓冲大约100字节(并且您可以继续使用sys.stdin=newin
从那时起将新文件对象用作标准输入)“因为这个领域过去在某些平台上有很多bug和问题(要提供完全通用性的跨平台功能是相当困难的)——我不确定它现在的状态,但我绝对建议在所有感兴趣的平台上进行彻底的测试,以确保一切顺利进行。(-u
,完全删除缓冲,如果可以满足您的要求,那么跨所有平台的问题应该会更少。)您只需使用sys.stdin.readline()
而不是sys.stdin。
:
这使我能够在Ubuntu 13.04上使用Python 2.7.4和Python 3.3.1进行行缓冲读取。sys.stdin.\uu iter\uuuu
仍然是行缓冲的,通过使用来生成sys.stdin.readline的迭代器,可以有一个行为基本相同的迭代器(在EOF时停止,而stdin.\uu iter\uu\uu不会)
import sys
for line in iter(sys.stdin.readline, ''):
sys.stdout.write('> ' + line.upper())
或者提供None
作为哨兵(但请注意,然后您需要自己处理EOF条件)。这在Python 3.4.3中对我很有效:
import os
import sys
unbuffered_stdin = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0)
上面说它只是open()
的别名
具有可选的缓冲参数:
缓冲是用于设置缓冲策略的可选整数。传递0以关闭缓冲(仅在二进制模式下允许),传递1以选择行缓冲(仅在文本模式下可用),传递大于1的整数以指示固定大小块缓冲区的字节大小
换言之:
- 完全无缓冲stdin需要二进制模式并将零作为缓冲区大小
- 行缓冲需要文本模式
- 任何其他缓冲区大小似乎都可以在二进制和文本模式下工作(根据文档)
我使用python 2.7的唯一方法是:
tty.setcbreak(sys.stdin.fileno())
这将完全禁用缓冲并抑制回音
编辑:关于Alex的回答,第一个命题(使用-u
调用python)在我的例子中是不可能的(请参阅)
第二个命题(使用较小的缓冲区复制fd:os.fdopen(sys.stdin.fileno(),'r',100)
)当我使用0或1的缓冲区时,它不起作用,因为它是用于交互式输入的,我需要立即处理按下的每个字符。可能是您的问题不在于Python,而在于Linux shell在将命令与管道链接时注入的缓冲区。当出现此问题时,输入不是按行缓冲的,而是按行缓冲的t乘以4K块
要停止此缓冲,请在命令链之前使用expect
包中的unbuffer
命令,例如:
unbuffer memcached -vv 2>&1 | unbuffer -p tee memkeywatch2010098.log 2>&1 | unbuffer -p ~/bin/memtracer.py | tee memkeywatchCounts20100908.log
<代码> un缓冲器< /C>命令在流水线的中间使用时需要<代码> -p>代码>。谢谢,在Linux环境中的-U标志是胜利者。我以前尝试使用OS.FDOPEN并进入相同的缓冲问题,即使我将缓冲区大小设置为10。不幸的是,Python 3仍然顽固地打开<代码> STDIN 处于缓冲文本模式。现在只有
stdout
和stderr
受-u
开关的影响。Python3有什么解决方法吗?可能是一个事件驱动库/选项?这在Python3.4.3中对我有效:os.fdopen(sys.stdin.fileno(),'rb',buffering=0)@DenilsonSáMaia:不需要自己重新打开它。sys.stdin
实际上是三层;一个io.TextIOWrapper
(解码bytes
到str
)包装一个io.BufferedReader
(缓冲bytes
)包装一个io.FileIO
(提交系统调用的实际对象)。它们都可以作为属性使用;sys.stdin.buffer
使用
tty.setcbreak(sys.stdin.fileno())
unbuffer memcached -vv 2>&1 | unbuffer -p tee memkeywatch2010098.log 2>&1 | unbuffer -p ~/bin/memtracer.py | tee memkeywatchCounts20100908.log