2011-08-04 17 views
11

Perl允許我在腳本中使用__DATA__標記來標記數據塊的開始。我可以使用DATA文件句柄讀取數據。在腳本中存儲數據塊的Pythonic方式是什麼?在Python腳本中存儲數據塊的Pythonic方式是什麼?

+2

把它放在一個單獨的文件(模塊)並導入它。不要這樣做。 – agf

+1

@agf - 我不同意。使用包含在StringIO中的三引號字符串內聯一個類文件對象,可以創建一個可移植且自包含的測試用例或演示腳本。 – PaulMcG

+0

謝謝! stackoverflow社區是驚人的! –

回答

8

這取決於你的數據,但字典和多行字符串都是非常好的方法。

state_abbr = { 
    'MA': 'Massachusetts', 
    'MI': 'Michigan', 
    'MS': 'Mississippi', 
    'MN': 'Minnesota', 
    'MO': 'Missouri', 
    } 

gettysburg = """ 
Four score and seven years ago, 
our fathers brought forth on this continent 
a new nation, 
conceived in liberty 
and dedicated to the proposition 
that all men are created equal. 
""" 
+2

如果它是二進制數據(即沒有字節,也沒有文本),可以通過在字符串前加b來包含這些數據。即:b「\ x00 \ x01 \ x16 \ x38」。這被Qt用來包含資源文件,例如 – Voo

+4

@Voo:b前綴沒有這樣做。它在Python 2中被忽略,並且在Python 3中意味着創建字節字面值而不是字符串(unicode)字面值。二進制數據可以作爲十六進制轉義包含在常規的未加前綴的字符串中。 –

+0

噢,是在Python3模式。當然,因爲Python 2中的「字符串」不是以unicode開頭的前綴,所以沒有多大意義。但是你真的允許在Python 3字符串中包含非法的unicode代碼點嗎?這是令人驚訝的,特別是因爲從字節(例如從套接字讀取)到unicode的轉換確實檢查它是否有意義。 – Voo

4

使用StringIO的模塊來創建一個在源文件的對象:

from StringIO import StringIO 

textdata = """\ 
Now is the winter of our discontent, 
Made glorious summer by this sun of York. 
""" 

# in place of __DATA__ = open('richard3.txt') 
__DATA__ = StringIO(textdata) 
for d in __DATA__: 
    print d 

__DATA__.seek(0) 
print __DATA__.readline() 

打印:

Now is the winter of our discontent, 

Made glorious summer by this sun of York. 

Now is the winter of our discontent, 

(我只是叫這個__DATA__與你原來的問題一致在實踐中,這不會是很好的Python命名風格 - 類似datafile會更合適。)

+4

切勿對標準魔術方法使用雙下劃線名稱。 – agf

0

不熟悉Perl的__DATA__變量Google告訴我它經常用於測試。假設你也在考慮測試你的代碼,你可能需要考慮doctest(http://docs.python.org/library/doctest.html)。例如,而不是

import StringIO 

__DATA__ = StringIO.StringIO("""lines 
of data 
from a file 
""") 

假設你想DATA是一個文件對象,現在你有什麼,你可以使用它像前進大多數其他文件的對象。例如:

if __name__=="__main__": 
    # test myfunc with test data: 
    lines = __DATA__.readlines() 
    myfunc(lines) 

但如果DATA的唯一用途是測試你可能最好創建一個文檔測試或寫入的PyUnit /鼻測試用例。

例如:

import StringIO 

def myfunc(lines): 
    r"""Do something to each line 

    Here's an example: 

    >>> data = StringIO.StringIO("line 1\nline 2\n") 
    >>> myfunc(data) 
    ['1', '2'] 
    """ 
    return [line[-2] for line in lines] 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 

運行這樣的那些測試:

$ python ~/doctest_example.py -v 
Trying: 
    data = StringIO.StringIO("line 1\nline 2\n") 
Expecting nothing 
ok 
Trying: 
    myfunc(data) 
Expecting: 
    ['1', '2'] 
ok 
1 items had no tests: 
    __main__ 
1 items passed all tests: 
    2 tests in __main__.myfunc 
2 tests in 2 items. 
2 passed and 0 failed. 
Test passed. 

文檔測試做了很多不同的東西,包括純文本文件中發現蟒蛇測試和運行它們。就個人而言,我不是一個大粉絲,喜歡更結構化的測試方法(import unittest),但它明確地測試一個代碼的pythonic方式。

0

IMO它高度依賴於數據的類型:如果你只有文本,並且可以確定沒有任何機會在裏面的'''或'「」,你可以使用這個版本的存儲文本,但是如果你想要怎麼做,例如,在一些已知'''或'「」的地方存儲或可能存在的文本?那麼我們建議你

  • 儲存或以任何方式編碼的數據
  • 把它放在一個單獨的文件

例:文字是

有許多' Python庫中的''和'「。

在這種情況下,可能很難通過三重報價。所以你可以做

__DATA__ = """There are many '''s and \"""s in Python libraries."""; 
print __DATA__ 

但是,在編輯或替換文本時,你必須注意。 在這種情況下,它可能會更有用做

$ python -c 'import sys; print sys.stdin.read().encode("base64")' 
There are many '''s and """s in Python libraries.<press Ctrl-D twice> 

那麼你得到

VGhlcmUgYXJlIG1hbnkgJycncyBhbmQgIiIicyBpbiBQeXRob24gbGlicmFyaWVzLg== 

作爲輸出。把它放到你的腳本中,如

__DATA__ = 'VGhlcmUgYXJlIG1hbnkgJycncyBhbmQgIiIicyBpbiBQeXRob24gbGlicmFyaWVzLg=='.decode('base64') 
print __DATA__ 

並查看結果。

相關問題