繁体   English   中英

为什么打印的字符在此python代码中消失了?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM