(这个问题源于试图绕过this problem)
我正在尝试在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',}]
你能解释一下这里发生了什么吗? (我在循环中跳过第一行,因为它包含另一个字典,输出变得更加疯狂,输出的混合部分)
P.S。:如果你有一个有效的选项来打印一个通用的python对象(类似于javascript中的JSON.stringify,但不需要处理JSON对象),请告诉我。
编辑:我的问题旨在解释这种奇怪的(对我来说)行为, 输出取决于括号后打印的内容。 实际上,如果我删除内部for循环(“for ps in 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}}]
答案 0 :(得分:0)
Python对象有两种方法用于获取其数据的快速人类可读表示:str,它为提供了一个可以打印的对象的可打印表示和repr提供一个可用于重建对象的字符串:对于许多类型,此函数尝试返回一个字符串,该字符串在传递给eval()时会产生具有相同值的对象。沉重的重要事件"尝试"。使用自己的__str__
和__repr__
方法,类可以自由覆盖默认实现。
您的示例输出:
'name': [String:ImageFileName]: 'leon.exe\x00'
很有意思。它显示rekall
模块覆盖__repr__
以提供其数据类型([String:ImageFileName]:
)的更复杂视图。但这不是有效的python - 实现者只是给出了更有类型的描述。它还显示其字符串'leon.exe\x00'
中包含不可打印的字符。这意味着,在这种情况下,在打印数据的字符串值时会发出NUL \x00
。我会称这是一个错误 - 但可能是该模块应该发出原始二进制数据。
控制台可以使用不可打印的字符进行格式化。例如,\r
(回车)告诉控制台在行的开头重新定位并覆盖字符
>>> print 'foo\rbar'
bar
在我的控制台上,这个转义序列
>>> print '\x1b[0;31;40m hello'
hello
制作"你好"用红色打印。
如果rekall
正在输出原始二进制数据,那么您尝试打印的字符串将具有不可打印的字符,从而弄乱您的控制台显示。为了使事情变得复杂,rekall
模块可能正在检查其stdout
是否是终端并更改其输出以向其字符串添加花哨的面向终端的格式。
假设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])))