我正在使用以下bash命令模式运行memcached:
memcached -vv 2>&1 | tee memkeywatch2010098.log 2>&1 | ~/bin/memtracer.py | tee memkeywatchCounts20100908.log
尝试跟踪平台范围内密钥的不匹配获取。
memtracer脚本位于下方并按预期工作,只有一个小问题。观察中间日志文件大小,memtracer.py直到memkeywatchYMD.log才开始输入 大小约为15-18K。是否有更好的方法来读取标准输入或者可能是将缓冲区大小降低到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], )
答案 0 :(得分:31)
您可以使用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.
除此之外,不支持更改现有文件的缓冲,但是可以使用与现有文件相同的基础文件描述符创建新文件对象,并且可能使用不同的缓冲。 {3}}。即,
import os
import sys
newin = os.fdopen(sys.stdin.fileno(), 'r', 100)
应将newin
绑定到文件对象的名称,该文件对象读取与标准输入相同的FD,但一次只缓冲大约100个字节(并且您可以继续{ {1}}从那里开始使用新文件对象作为标准输入。我说“应该”,因为这个区域使用在某些平台上存在许多错误和问题(提供跨平台的完全通用性非常困难) - 我不确定它是什么现在状态,但我肯定建议在所有感兴趣的平台上进行全面测试,以确保一切顺利。 (sys.stdin = newin
,完全删除缓冲,如果可能满足您的要求,应该可以在所有平台上使用更少的问题。)
答案 1 :(得分:22)
您只需使用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进行行缓冲读取。
答案 2 :(得分:10)
sys.stdin.__iter__
仍然是行缓冲的,通过使用the 2-argument form of iter
来构造迭代器,可以有一个迭代器,其行为大多相同(在EOF停止,而stdin.__iter__
不会) sys.stdin.readline
:
import sys
for line in iter(sys.stdin.readline, ''):
sys.stdout.write('> ' + line.upper())
或者提供None
作为哨兵(但请注意,您需要自己处理EOF条件)。
答案 3 :(得分:3)
这在Python 3.4.3中适用于我:
procedure TFrmsearchpage.btnloadClick(Sender: TObject);
var
con:tfdconnection;
loadquery:tfdquery;
i:integer;
j:integer;
row:integer;
col1,col2,col3,col4, col5, col6, col7 : string;
begin
con:=tfdconnection.Create(nil);
loadquery:=tfdquery.Create(con);
loadquery.Connection:=con;
con.DriverName:='SQL';
con.Open('DriverID=SQLite;Database='+Dir+'/Stock_V5;');
loadquery.SQL.Text:='SELECT * FROM ' + edtdatabasename.Text; //' Con Column';
loadquery.Open;
if loadquery.Eof then
ShowMessage('not exists')
else
ShowMessage('exists');
for i := 0 to sgdproduct.RowCount do
for j := 0 to sgdproduct.ColCount do
sgdproduct.Cells[i,j]:='';
showmessage(loadquery.SQL.Text);
Sgdproduct.colcount:=7;
sgdproduct.fixedcols:=0;
for i := 0 to 3 do
sgdproduct.colwidths[i]:=100;
sgdproduct.cells[0,0] := 'Col1'; //?
sgdproduct.cells[1,0] := 'Col2'; //?
sgdproduct.cells[2,0] := 'Col3';
sgdproduct.cells[3,0] := 'Col4'; //?
sgdproduct.cells[4,0] := 'Col5'; //?
sgdproduct.cells[5,0] := 'Col6'; //?
sgdproduct.cells[6,0] := 'Col7'; //?
row:=1;
while not loadquery.Eof do
begin
Col1:=query.FieldByName('Col1')//.As
Col2:=query.FieldByName('Col2')//.As
Col3:=query.FieldByName('Col3')//.As
Col4:=query.FieldByName('Col4')//.As
Col5:=query.FieldByName('Col5')//.As
Col6:=query.FieldByName('Col6')//.As
col7:=query.FieldByName('Col7')//.As
sgdproduct.Cells[0,row]:=Col1;
sgdproduct.Cells[1,row]:=Col2;
sgdproduct.Cells[2,row]:=Col3;
sgdproduct.Cells[3,row]:=Col4;
sgdproduct.Cells[4,row]:=Col5;
sgdproduct.Cells[5,row]:=Col6;
sgdproduct.Cells[6,row]:=Col7;
row:=row+1;
query.Next;
end;
end;
documentation for fdopen()
表示它只是import os
import sys
unbuffered_stdin = os.fdopen(sys.stdin.fileno(), 'rb', buffering=0)
的别名。
open()
有一个可选的open()
参数:
buffering 是一个可选的整数,用于设置缓冲策略。传递0以切换缓冲关闭(仅允许在二进制模式下),1选择行缓冲(仅在文本模式下可用),以及整数&gt; 1表示固定大小的块缓冲区的大小(以字节为单位)。
换句话说:
答案 4 :(得分:1)
您的麻烦可能不在于Python,而是Linux外壳程序在与管道链接命令时注入的缓冲。遇到问题时,输入不是按行缓冲,而是按4K块缓冲。
要停止此缓冲,请在命令链之前使用unbuffer
软件包中的expect
命令,例如:
unbuffer memcached -vv 2>&1 | unbuffer -p tee memkeywatch2010098.log 2>&1 | unbuffer -p ~/bin/memtracer.py | tee memkeywatchCounts20100908.log
在管道中间使用时,unbuffer
命令需要-p
选项。
答案 5 :(得分:0)
我用python 2.7做的唯一方法是:
tty.setcbreak(sys.stdin.fileno())
来自Python nonblocking console input的。这样可以完全禁用缓冲并抑制回声。
编辑:关于亚历克斯的答案,在我的案例中,第一个命题(用-u
调用python)是不可能的(见shebang limitation)。
当我使用0或1的缓冲区时,第二个命题(用较小的缓冲区复制fd:os.fdopen(sys.stdin.fileno(), 'r', 100)
)不起作用,因为它是用于交互式输入的,我需要立即处理每个按下的字符。