Я наблюдаю "плохой адрес" 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
Очевидно, что здесь нужно сделать файл mmap вместо read (хотя это означает, что у вас есть bytes, а не str), что и делают такие инструменты, как grep, или обрабатывать его итеративно, а не все сразу, как например, инструменты head делаю.
Кроме того, сколько у вас памяти? Чтобы прочитать текстовый файл UTF-8 размером 39 ГБ, который в основном ASCII, но содержит несколько астральных символов, требуется около 156 ГБ для последней строки.
В любом случае, возможно, что вы может читаете весь файл в память, но вы не могу делаете все это на одном read(). Особенно, если вы используете Python 2.x, но, возможно, даже с 3.x. Например, ваш Python может в конечном итоге использовать более старый вызов read, который использует 32-битный размер и терпит неудачу, если он больше, чем 1<<31.
@zvone, проблема в том, что я использую другую библиотеку ввода-вывода, которая в конечном итоге вызывает read() для дескриптора файла, поэтому, хотя я хотел бы читать по частям за раз, что существенно усложнит проблему ввода-вывода.
@abarnert, это полезная информация; Я зарезервировал только 64 ГБ ОЗУ, посмотрю, получится ли по-другому с доступными 200 ГБ +. Если увеличение предела памяти здесь не помогает, я думаю, что очевидным будет, вероятно, написать свой собственный код ввода-вывода и прочитать его итеративно / memmap.
@ Suriname0 Что ж, если у вас есть огромный файл, слишком большой для загрузки сразу, и вы используете библиотеку, которая должна прочитать весь файл сразу, вам, возможно, придется признать, что эта библиотека не соответствует вашим потребностям. : \
Я думаю, проблема заключалась в том, что определил abarnert: в необходимости увеличения объема памяти. Я также переключился на метод пакетного чтения + конкатенация в памяти, и он работает лучше. Это не имеет прямого отношения к этой проблеме, но я также отмечу, что столкнулся со следующей ошибкой, о которой не знал: issues.apache.org/jira/browse/ARROW-1907






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