2011-08-04 16 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__ 

并查看结果。

相关问题