Похоже, ваша основная проблема в том, что ваш оператор try / catch в настоящее время останавливает выполнение при первой обнаруженной ошибке. Чтобы продолжить выдавать файлы при возникновении ошибки, вам нужно поместить ваш try/catch
дальше в цикл for, то есть вы можете обернуть менеджер контекста with open
.
Обратите также внимание, что в Python одеяло try/catch
считается анти-шаблоном, поэтому обычно вам нужно явно отлавливать и обрабатывать ошибки вместо использования общего назначения Exception
. Я включил более явные IOerror
и OSError
в качестве примеров.
Наконец, поскольку вы можете отлавливать ошибки в самом генераторе, функция nlp.pipe
больше не нуждается в параметре as_tuple
.
from pathlib import Path
import spacy
def grab_files(path):
for path in Path(path).rglob('*'):
if path.is_file():
try:
with open(str(path), 'r', encoding='utf-8', errors='ignore') as f:
yield f.read()
except (OSError, IOError) as err:
print(f'ERROR: {path}', err)
nlp = spacy.load('en')
for doc in nlp.pipe(grab_files('C:/Temp/tmp/'), batch_size=1000):
print(doc) # ... do something with spacy Doc here
* Редактировать - чтобы ответить на дополнительный вопрос.
Обратите внимание, что вы по-прежнему читаете содержимое текстовых документов по одному, как если бы вы работали без генератора, однако выполнение этого с помощью генератора возвращает объект, который задерживает выполнение до тех пор, пока вы не передадите его в nlp.pipe
метод. Затем SpaCy обрабатывает одну партию текстовых документов одновременно с помощью своей внутренней функции util.minibatch
. Эта функция оканчивается на yield list(batch)
, который выполняет код, который открывает / закрывает файлы (по 1000 в вашем случае). Что касается любых ошибок, не связанных с SpaCy, то есть ошибок, связанных с открытием / чтением файла, код, который я разместил, должен работать как есть.
Однако в том виде, в каком он есть, и ваш os.walk
, и мой Path(path).rglob
без разбора выбирают любой файл в каталоге независимо от его типа. Например, если в вашей папке /tmp
есть файл .png
, то SpaCy вызовет TypeError
во время процесса токенизации. Если вы хотите зафиксировать подобные ошибки, лучше всего их предвидеть и избегать, прежде чем отправлять их в SpaCy, например, внося в свой код белый список, который допускает только определенные расширения файлов (.rglob('*.txt')
).
Если вы работаете над проектом, который по тем или иным причинам не может быть прерван из-за ошибки, независимо от стоимости. И если предположить, что вам абсолютно необходимо знать, на какой стадии конвейера произошла ошибка, то одним из подходов может быть создание настраиваемого компонента конвейера для каждого компонента конвейера SpaCy по умолчанию (Tagger, DependencyParser и т. Д.), Который вы собираетесь использовать. Затем вам нужно будет обернуть указанные компоненты в общую логику обработки / регистрации ошибок. Сделав это, вы сможете обработать свои файлы, используя свой полностью настроенный конвейер. Но, если в твоей голове нет пистолета, я бы его не рекомендовал. Намного лучше было бы предвидеть ошибки, которые вы ожидаете, и обрабатывать их внутри вашего генератора. Возможно, у кого-то с лучшим знанием внутренних органов SpaCy будет лучшее предложение.