2011-08-04 8 views
11

Perlでは、スクリプト内で__DATA__トークンを使用してデータブロックの開始をマークできます。 DATAファイルハンドルを使用してデータを読み取ることができます。スクリプトにデータブロックを格納するPythonの方法は何ですか?Pythonスクリプトにデータブロックを格納するPythonの方法は何ですか?

+2

別のファイル(モジュール)に入れてインポ​​ートします。それをインラインではしないでください。 – agf

+1

@agf - 私は同意しません。 StringIOで囲まれた三重引用符で囲まれた文字列を使用してファイルライクなオブジェクトをインライン展開すると、移植性のある自己完結型のテストケースまたはデモスクリプトが作成されます。 – PaulMcG

+0

ありがとう! stackoverflowコミュニティは素晴らしいです! –

答えて

8

それはあなたのデータに依存しますが、dictリテラルと複数行の文字列はどちらも本当に良い方法です。

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の "文字列"は接頭辞で始まるユニコードではないのであまり意味がありません。しかし、実際に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 
""") 

の例。たとえば:

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

が、データの使用のみがあなたをテストするためである場合は、おそらくのdoctestを作成したり、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. 

doctestでは、プレーンテキストファイルでPythonのテストを発見し、それらを実行しているなど、さまざまな多くのことを行います。個人的には、私は大きなファンではなく、より構造化されたテスト手法(import unittest)を好むが、それは明白に1つのコードをテストする無限の方法である。

0

IMOそれはデータの種類に大きく依存します:あなたはテキストのみを持っていて、機会が邪魔していないことを確かめることができます。しかし、もしあなたが望むなら、例えば、そこにあるかそこにあるかもしれないことが分かっているところに何かのテキストを保存したいのですか?そして、それは

  • のいずれかにadviseableである任意の方法で符号化されたデータまたはを保存
  • は別のファイルにそれを置く

例:テキストは

は「多くありますです'' sとPythonライブラリの "" "s"

この場合、3重引用符では難しい場合があります。そうすることができます

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

しかし、テキストの編集や置き換えには注意が必要です。この場合 、あなたが出力として

VGhlcmUgYXJlIG1hbnkgJycncyBhbmQgIiIicyBpbiBQeXRob24gbGlicmFyaWVzLg== 

を取得

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

を行うことがより便利かもしれません。これをとり、

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

などのようにスクリプトに入れて、結果を確認してください。

関連する問題