[英]Why do printed characters disappear in this python code?
(这个问题源于试图解决这个问题 )
我正在尝试在python中打印字典列表。 由于我找不到能够将python对象转换为字符串的真实函数(不,json.dumps不起作用),因此我想编写一个简单的打印脚本。
不幸的是,该行开头的字符完全消失了……现在,我可能不是python的专家,但是这种行为对我来说似乎毫无意义。
# The out object is returned by a library (rekall)
# and it is a list of dictionaries.
import rekall
out = rekall.a_modified_module.calculate()
print '[',
for ps in out:
first = True
print '{',
for info in ps:
if first:
first = False
else:
print '\'%s\':\'%s\',' % (info, ps[info]),
print '}',
print ']'
我希望输出为:
[{'pid':'2040', 'name':'leon.exe', 'offset':'2234185984',}]
相反,我得到这个:
'pid':'2040', 'name':'leon.exe', 'offset':'2234185984',}]
您能给我解释一下这是怎么回事吗? (我跳过了循环的第一行,因为它包含另一个词典,并且输出变得更加疯狂,并且输出部分混合在一起)
PS:如果您有一个有效的选项来打印通用python对象(类似于javascript中的JSON.stringify,但不必处理JSON对象),请告诉我。
编辑:我的问题旨在解释这种(对我而言)奇怪的行为,其中输出取决于括号后打印的内容。 实际上,如果删除内部的for循环(“ ps中的信息”),则初始括号会正确打印。 另外,如果我创建管道将输出发送到另一个程序,则该程序将从括号开始正确接收输出。
编辑:为了帮助理解问题的性质以及'out'对象的类型,这是使用'pprint'模块的输出:
[{'name': [String:ImageFileName]: 'leon.exe\x00',
'offset': 2236079360,
'pid': [unsigned int:UniqueProcessId]: 0x000007FC,
'psscan': {'CSRSS': False,
'Handles': False,
'PsActiveProcessHead': True,
'PspCidTable': True,
'Sessions': True}}]
Python对象有两种方法可用于快速获取其数据的人类可读表示形式: str 表示对象的可打印表示形式, repr尝试提供可用于重建对象的字符串: 对于许多类型,这函数尝试返回一个字符串,该字符串在传递给eval()时将产生具有相同值的对象 。 重在“尝试”。 类可以使用自己的__str__
和__repr__
方法随意覆盖默认实现。
您的示例输出:
'name': [String:ImageFileName]: 'leon.exe\x00'
很有趣。 它显示rekall
模块正在重写__repr__
以提供其数据类型的更复杂视图( [String:ImageFileName]:
__repr__
。 但这不是有效的python-实现者只是给出了更详细的描述。 它还显示其字符串'leon.exe\\x00'
包含不可打印的字符。 这意味着在这种情况下,在打印数据的字符串值时会发出NUL \\x00
。 我将其称为错误-但它可能是模块应该发出原始二进制数据。
控制台可能会使用不可打印的字符进行格式化。 例如, \\r
(回车)告诉控制台在行首重新定位并覆盖字符
>>> print 'foo\rbar'
bar
在我的控制台上,此转义序列
>>> print '\x1b[0;31;40m hello'
hello
使“ hello”打印为红色。
如果rekall
正在输出原始二进制数据,则您尝试打印的字符串具有不可打印的字符,会弄乱您的控制台显示。 为了使事情复杂, rekall
模块可能正在检查其stdout
是否为终端,并更改其输出以在其字符串中添加面向终端的rekall
格式。
假设rekall
将原始二进制数据放入字符串中,则可以执行str
摆脱rekall
元数据,然后repr
摆脱麻烦的字符
def mystr(s):
return repr(str(s))
for ps in out:
first = True
for info in ps:
if first:
first = False
else:
print '\'%s\':\'%s\'' % (mystr(info), mystr(ps[info])))
或编写自己的函数以过滤掉不需要的字符。 这在Unicode中有点困难,但是对于ascii文本,我们可以采用在string.printable
可以找到的一部分字符。
printable = set(
'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$'
'%&\\\'()*+,-./:;<=>?@[\\]^_`{|}~ \t')
def mystr(s):
return ''.join(filter(printable.__contains__, str(s)))
for ps in out:
first = True
for info in ps:
if first:
first = False
else:
print '\'%s\':\'%s\'' % (mystr(info), mystr(ps[info])))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.