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