Что такое Pythonic способ хранения блока данных в Python script?

Perl позволяет мне использовать токен __DATA__ в script, чтобы отметить начало блока данных. Я могу читать данные с помощью дескриптора файла DATA. Что такое питоновский способ хранения блока данных в script?

Ответ 1

Это зависит от ваших данных, но литералы 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

Используйте модуль 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 будет более подходящим.)

Ответ 3

Не знакомо с переменной 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/Nose.

Например:

import StringIO

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

    Here 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), но он однозначно является питоническим способом тестирования кода.

Ответ 4

IMO сильно зависит от типа данных: если у вас есть только текст и вы можете быть уверены, что не существует '' 'или' ", который, возможно, будет внутри, вы можете использовать эту версию хранения текста. Но что делать, если вы хотите, например, сохранить какой-то текст, где известно, что" или "" есть" или могут быть там? Тогда рекомендуется

  • либо хранить кодированные данные каким-либо образом, либо
  • поместите его в отдельный файл

Пример: текст

В библиотеках Python существует множество "и" и "s".

В этом случае это может быть трудно сделать с помощью тройной цитаты. Таким образом, вы можете сделать

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

Но вы должны обратить внимание при редактировании или замене текста. В этом случае было бы более полезно сделать

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

тогда вы получите

VGhlcmUgYXJlIG1hbnkgJycncyBhbmQgIiIicyBpbiBQeXRob24gbGlicmFyaWVzLg==

в качестве вывода. Возьмите это и поместите в свой script, например, в

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

и посмотрите результат.