简体   繁体   English

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

[英]Why do printed characters disappear in this python code?

(This question rised from an attempt to get around this problem ) (这个问题源于试图解决这个问题

I'm trying to print a list of dictionaries in python. 我正在尝试在python中打印字典列表。 Since I can't find a real function which is able to convert a python object to a string (no, json.dumps doesn't work), I thought to write a simple printing script. 由于我找不到能够将python对象转换为字符串的真实函数(不,json.dumps不起作用),因此我想编写一个简单的打印脚本。

Unfortunately characters at the beginning of the line simply disappear... Now, I'm probably no expert in python, but this behavior looks nonsense to me. 不幸的是,该行开头的字符完全消失了……现在,我可能不是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 ']'

I would expect the output to be: 我希望输出为:

[{'pid':'2040', 'name':'leon.exe', 'offset':'2234185984',}]

Instead I get this: 相反,我得到这个:

'pid':'2040', 'name':'leon.exe', 'offset':'2234185984',}]

Can you please explain me what's happening here? 您能给我解释一下这是怎么回事吗? (I'm skipping first line in the loop because it contains another dictionary and the output gets even crazier, with mixed parts of the output) (我跳过了循环的第一行,因为它包含另一个词典,并且输出变得更加疯狂,并且输出部分混合在一起)

PS: if you have a valid option for printing a generic python object (something comparable to JSON.stringify in javascript, but without having to deal with JSON objects) please tell me. PS:如果您有一个有效的选项来打印通用python对象(类似于javascript中的JSON.stringify,但不必处理JSON对象),请告诉我。

EDIT: My question aims at explaining this strange (to me) behavior, where the output depends on what is printed after the brackets. 编辑:我的问题旨在解释这种(对我而言)奇怪的行为,其中输出取决于括号后打印的内容。 In fact, if I remove the inner for loop ("for info in ps"), the initial brackets are printed correctly. 实际上,如果删除内部的for循环(“ ps中的信息”),则初始括号会正确打印。 Also, if I create a pipe to send the output to another program, that program will receive the output correctly, starting from the brackets. 另外,如果我创建管道将输出发送到另一个程序,则该程序将从括号开始正确接收输出。

EDIT: To help understanding the nature of the problem, and the type of the 'out' object, this is the output using the 'pprint' module: 编辑:为了帮助理解问题的性质以及'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 objects have two methods used to get a quick human-readable representation of its data: str which gives a nicely printable representation of an object and repr which attempts to give a string that could be used to rebuild the object: For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval() . Python对象有两种方法可用于快速获取其数据的人类可读表示形式: str 表示对象的可打印表示形式, repr尝试提供可用于重建对象的字符串: 对于许多类型,这函数尝试返回一个字符串,该字符串在传递给eval()时将产生具有相同值的对象 Heavy emphassis on "attempts". 重在“尝试”。 Classes are free to override the default implementation with their own __str__ and __repr__ methods. 类可以使用自己的__str____repr__方法随意覆盖默认实现。

Your example output: 您的示例输出:

'name':  [String:ImageFileName]: 'leon.exe\x00'

is interesting. 很有趣。 It shows that the rekall module is overriding __repr__ to give a more complex view of its data types ( [String:ImageFileName]: ). 它显示rekall模块正在重写__repr__以提供其数据类型的更复杂视图( [String:ImageFileName]: __repr__ But that's not valid python - the implementors were just giving a more typeful description. 但这不是有效的python-实现者只是给出了更详细的描述。 It also shows that its strings 'leon.exe\\x00' have non-printable characters in them. 它还显示其字符串'leon.exe\\x00'包含不可打印的字符。 It means that, in this instance, a NUL \\x00 is emitted when printing the string value of the data. 这意味着在这种情况下,在打印数据的字符串值时会发出NUL \\x00 I would call this a bug - but it could be that the module is supposed to emit raw binary data. 我将其称为错误-但它可能是模块应该发出原始二进制数据。

Non-printable characters may be used for formatting by your console. 控制台可能会使用不可打印的字符进行格式化。 For instance, \\r (carriage return) tells the console to reposition at the start of the line and overwrite characters 例如, \\r (回车)告诉控制台在行首重新定位并覆盖字符

>>> print 'foo\rbar'
bar

On my console, this escape sequence 在我的控制台上,此转义序列

>>> print '\x1b[0;31;40m hello'
hello

makes "hello" print in red. 使“ hello”打印为红色。

If rekall is putting out raw binary data, strings you are trying to print have non-printable characters that mess up your console display. 如果rekall正在输出原始二进制数据,则您尝试打印的字符串具有不可打印的字符,会弄乱您的控制台显示。 To keep things complicated, the rekall module may be checking whether its stdout is a terminal and changing its output to add fancy terminal-oriented formatting to its strings. 为了使事情复杂, rekall模块可能正在检查其stdout是否为终端,并更改其输出以在其字符串中添加面向终端的rekall格式。

Assuming that rekall is putting raw binary data in strings you could do str to get rid of rekall metadata and then repr to escape the troublesome characters 假设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])))

Or write your own function to filter out characters you don't want. 或编写自己的函数以过滤掉不需要的字符。 This is kinda difficult in Unicode but for ascii text we could take a subset of the characters you would find in string.printable . 这在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