Python OSError: неверный адрес при чтении из большого файла

Я наблюдаю "плохой адрес" OSError при чтении из дескриптора файла, созданного с использованием синтаксиса with в Python 3.

Размер этого файла составляет 39 ГБ, но у меня должно быть достаточно оперативной памяти, чтобы прочитать весь файл. Сообщение об ошибке наводит меня на мысль, что я попал в какое-то ограничение ОС; Я использую CentOS 6.9. Может ли кто-нибудь помочь мне понять, что может вызывать такое поведение?

Файл отлично читается за пределами Python, например. в bash с head или vim.

Ниже показан упрощенный пример кода, вызывающего ошибку:

In [2]: with open(filename, 'r', encoding = "utf8") as infile:
   ...:     infile.read()
   ...:     
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-2-3f216811bec7> in <module>()
  1 with open(filename, 'r', encoding = "utf8") as infile:
----> 2     infile.read()
  3 

OSError: [Errno 14] Bad address

Вы делаете это в iPython, поэтому он пытается не только прочитать 39 ГБ, но и распечатать их. Это может быть связано с проблемой и на самом деле может потребовать значительных накладных расходов на требуемую память. В любом случае, вам, вероятно, не следует читать весь файл такого размера в память сразу, даже если у вас достаточно оперативной памяти для этого ...

zvone 01.06.2018 01:20

Очевидно, что здесь нужно сделать файл mmap вместо read (хотя это означает, что у вас есть bytes, а не str), что и делают такие инструменты, как grep, или обрабатывать его итеративно, а не все сразу, как например, инструменты head делаю.

abarnert 01.06.2018 01:33

Кроме того, сколько у вас памяти? Чтобы прочитать текстовый файл UTF-8 размером 39 ГБ, который в основном ASCII, но содержит несколько астральных символов, требуется около 156 ГБ для последней строки.

abarnert 01.06.2018 01:33

В любом случае, возможно, что вы может читаете весь файл в память, но вы не могу делаете все это на одном read(). Особенно, если вы используете Python 2.x, но, возможно, даже с 3.x. Например, ваш Python может в конечном итоге использовать более старый вызов read, который использует 32-битный размер и терпит неудачу, если он больше, чем 1<<31.

abarnert 01.06.2018 01:38

@zvone, проблема в том, что я использую другую библиотеку ввода-вывода, которая в конечном итоге вызывает read() для дескриптора файла, поэтому, хотя я хотел бы читать по частям за раз, что существенно усложнит проблему ввода-вывода.

Suriname0 01.06.2018 16:16

@abarnert, это полезная информация; Я зарезервировал только 64 ГБ ОЗУ, посмотрю, получится ли по-другому с доступными 200 ГБ +. Если увеличение предела памяти здесь не помогает, я думаю, что очевидным будет, вероятно, написать свой собственный код ввода-вывода и прочитать его итеративно / memmap.

Suriname0 01.06.2018 16:18

@ Suriname0 Что ж, если у вас есть огромный файл, слишком большой для загрузки сразу, и вы используете библиотеку, которая должна прочитать весь файл сразу, вам, возможно, придется признать, что эта библиотека не соответствует вашим потребностям. : \

zvone 01.06.2018 16:20

Я думаю, проблема заключалась в том, что определил abarnert: в необходимости увеличения объема памяти. Я также переключился на метод пакетного чтения + конкатенация в памяти, и он работает лучше. Это не имеет прямого отношения к этой проблеме, но я также отмечу, что столкнулся со следующей ошибкой, о которой не знал: issues.apache.org/jira/browse/ARROW-1907

Suriname0 02.06.2018 16:09
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
8
3 327
0

Другие вопросы по теме