Можем ли мы использовать переменную python для хранения всего файла? - PullRequest
7 голосов
/ 16 сентября 2009

При условии, что мы знаем, что весь файл будет загружен в память, и мы можем себе это позволить, Каковы недостатки (если есть) или ограничения (если есть) загрузки всего файла (возможно, двоичного файла) в переменную python. Если это технически возможно, следует ли этого избегать и почему?

Что касается размера файла, то каким максимальным размером должно ограничиваться это решение? А почему?

Фактический код загрузки может быть тем, который предложен в этой записи в стеке .

Пример кода:

def file_get_contents(filename):
    with open(filename) as f:
        return f.read()

content = file_get_contents('/bin/kill')

... code manipulating 'content' ...

[EDIT] Манипулирование кодом, которое приходит на ум (но, возможно, не применимо), - это стандартные операторы списка / строк (квадратные скобки, знаки «+») или некоторые строковые операторы («len», «in», «count», «endsith» /). 'setswith', 'split', 'translation' ...).

Ответы [ 6 ]

11 голосов
/ 16 сентября 2009
  • Да, вы можете
  • Единственным недостатком является использование памяти, а также возможная скорость, если файл большой.
  • Размер файла должен быть ограничен количеством места в памяти.

В общем, есть лучшие способы сделать это, но для одноразовых скриптов, где вы знаете, память не проблема, конечно.

8 голосов
/ 17 сентября 2009

Хотя вы получили хорошие ответы, кажется, что никто не ответил на эту часть вашего вопроса (как часто бывает, когда вы задаете много вопросов в вопросе; -) ...:

Относительно размера файла, к чему максимальный размер этого решения должен быть ограничено ?. И почему?

Самым важным является то, сколько физической памяти может на самом деле этот конкретный процесс Python использовать (так называемый «рабочий набор»), без чрезмерного ухудшения других аспектов производительности системы в целом. Если вы превысите физическую ОЗУ для своего «рабочего набора», вы будете разбивать на страницы и выгружать и выгружать на диск, и ваша производительность может быстро ухудшаться (до состояния, известного как «перебивание», когда все доступные циклы переходят к задачи ввода и вывода страниц, и незначительное количество фактической работы может быть фактически выполнено).

Из этого общего количества, довольно скромное количество (скажем, не более нескольких МБ в общем), вероятно, будет использовано исполняемым кодом (собственными исполняемыми файлами Python, DLL или .so), а также байт-кодом и общими вспомогательными структурами данных. которые активно нужны в памяти; на типичной современной машине, которая не выполняет другие важные или срочные задачи, вы можете почти игнорировать эти издержки по сравнению с гигабайтами оперативной памяти, которые у вас есть в целом (хотя ситуация может быть другой во встроенных системах и т. д.).

Все остальное доступно для ваших данных - включая этот файл, который вы читаете в память, а также любые другие важные структуры данных. «Модификации» данных файла обычно могут занимать (временно) вдвое больше памяти, чем размер содержимого файла (если вы держите его в строке), - конечно, больше, если вы храните копию старые данные, а также создание новых модифицированных копий / версий.

Так что для использования «только для чтения» на типичной современной 32-разрядной машине с, скажем, 2 ГБ ОЗУ в целом, чтение в память (скажем) 1,5 ГБ не должно быть проблемой; но это должно быть существенно меньше 1 ГБ, если вы делаете «модификации» (и даже меньше, если у вас есть другие важные структуры данных в памяти!). Конечно, на выделенном сервере с 64-разрядной сборкой Python, 64-разрядной ОС и 16 ГБ оперативной памяти практические ограничения раньше сильно отличались - примерно пропорционально разному количеству доступной оперативной памяти.

Например, текст Библии короля Иакова как загружаемый здесь (разархивированный) составляет около 4,4 МБ; Таким образом, на машине с 2 ГБ ОЗУ вы можете хранить около 400 слегка измененных копий в памяти (если больше ничего не запрашивает память), но на машине с 16 (доступными и адресуемыми) ГБ ОЗУ храните более 3000 таких копий.

4 голосов
/ 16 сентября 2009
with open(filename) as f:

Это работает только на Python 2.x в Unix. Это не будет делать то, что вы ожидаете на Python 3.x или на Windows, так как они оба проводят четкое различие между текстовыми и двоичными файлами. Лучше указать, что файл является двоичным, например:

with open(filename, 'rb') as f:

Это отключит преобразование CR / LF ОС в Windows и заставит Python 3.x возвращать байтовый массив, а не символы Юникода.

Что касается остальной части вашего вопроса, я согласен с (неотредактированным) ответом Леннарта Регебро.

3 голосов
/ 16 сентября 2009

Единственная проблема, с которой вы можете столкнуться - это потребление памяти: строки в Python неизменны. Поэтому, когда вам нужно изменить байт, вам нужно скопировать старую строку:

new = old[0:pos] + newByte + old[pos+1:]

Это требует до трехкратной памяти old.

Вместо строки вы можете использовать массив . Они предлагают гораздо лучшую производительность, если вам нужно изменить содержимое, и вы можете легко создавать их из строки.

1 голос
/ 07 июня 2012

Вы также можете использовать функцию Python v3:

>>> ''.join(open('htdocs/config.php', 'r').readlines())
"This is the first line of the file.\nSecond line of the file"

Подробнее здесь http://docs.python.org/py3k/tutorial/inputoutput.html

0 голосов
/ 16 сентября 2009

Да, вы можете - при условии, что файл достаточно мал -.

Даже очень питонно дополнительно преобразовывать возвращаемое значение read () в любой контейнер / итерируемый тип, как, скажем, string.split (), вместе со связанными функциями функционального программирования для продолжения обработки файла "сразу".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...