簡體   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