File Directory#

This covers how to use the DirectoryLoader to load all documents in a directory. Under the hood, by default this uses the UnstructuredLoader

from langchain.document_loaders import DirectoryLoader

We can use the glob parameter to control which files to load. Note that here it doesnโ€™t load the .rst file or the .ipynb files.

loader = DirectoryLoader('../', glob="**/*.md")
docs = loader.load()
len(docs)
1

Show a progress bar#

By default a progress bar will not be shown. To show a progress bar, install the tqdm library (e.g. pip install tqdm), and set the show_progress parameter to True.

%pip install tqdm
loader = DirectoryLoader('../', glob="**/*.md", show_progress=True)
docs = loader.load()
Requirement already satisfied: tqdm in /Users/jon/.pyenv/versions/3.9.16/envs/microbiome-app/lib/python3.9/site-packages (4.65.0)
0it [00:00, ?it/s]

Use multithreading#

By default the loading happens in one thread. In order to utilize several threads set the use_multithreading flag to true.

loader = DirectoryLoader('../', glob="**/*.md", use_multithreading=True)
docs = loader.load()

Change loader class#

By default this uses the UnstructuredLoader class. However, you can change up the type of loader pretty easily.

from langchain.document_loaders import TextLoader
loader = DirectoryLoader('../', glob="**/*.md", loader_cls=TextLoader)
docs = loader.load()
len(docs)
1

If you need to load Python source code files, use the PythonLoader.

from langchain.document_loaders import PythonLoader
loader = DirectoryLoader('../../../../../', glob="**/*.py", loader_cls=PythonLoader)
docs = loader.load()
len(docs)
691

Auto detect file encodings with TextLoader#

In this example we will see some strategies that can be useful when loading a big list of arbitrary files from a directory using the TextLoader class.

First to illustrate the problem, letโ€™s try to load multiple text with arbitrary encodings.

path = '../../../../../tests/integration_tests/examples'
loader = DirectoryLoader(path, glob="**/*.txt", loader_cls=TextLoader)

A. Default Behavior#

loader.load()
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Traceback (most recent call last) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ /data/source/langchain/langchain/document_loaders/text.py:29 in load                             โ”‚
โ”‚                                                                                                  โ”‚
โ”‚   26 โ”‚   โ”‚   text = ""                                                                           โ”‚
โ”‚   27 โ”‚   โ”‚   with open(self.file_path, encoding=self.encoding) as f:                             โ”‚
โ”‚   28 โ”‚   โ”‚   โ”‚   try:                                                                            โ”‚
โ”‚ โฑ 29 โ”‚   โ”‚   โ”‚   โ”‚   text = f.read()                                                             โ”‚
โ”‚   30 โ”‚   โ”‚   โ”‚   except UnicodeDecodeError as e:                                                 โ”‚
โ”‚   31 โ”‚   โ”‚   โ”‚   โ”‚   if self.autodetect_encoding:                                                โ”‚
โ”‚   32 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   detected_encodings = self.detect_file_encodings()                       โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /home/spike/.pyenv/versions/3.9.11/lib/python3.9/codecs.py:322 in decode                         โ”‚
โ”‚                                                                                                  โ”‚
โ”‚    319 โ”‚   def decode(self, input, final=False):                                                 โ”‚
โ”‚    320 โ”‚   โ”‚   # decode input (taking the buffer into account)                                   โ”‚
โ”‚    321 โ”‚   โ”‚   data = self.buffer + input                                                        โ”‚
โ”‚ โฑ  322 โ”‚   โ”‚   (result, consumed) = self._buffer_decode(data, self.errors, final)                โ”‚
โ”‚    323 โ”‚   โ”‚   # keep undecoded input until the next call                                        โ”‚
โ”‚    324 โ”‚   โ”‚   self.buffer = data[consumed:]                                                     โ”‚
โ”‚    325 โ”‚   โ”‚   return result                                                                     โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xca in position 0: invalid continuation byte

The above exception was the direct cause of the following exception:

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Traceback (most recent call last) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ in <module>:1                                                                                    โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ โฑ 1 loader.load()                                                                                โ”‚
โ”‚   2                                                                                              โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /data/source/langchain/langchain/document_loaders/directory.py:84 in load                        โ”‚
โ”‚                                                                                                  โ”‚
โ”‚   81 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   if self.silent_errors:                                              โ”‚
โ”‚   82 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   logger.warning(e)                                               โ”‚
โ”‚   83 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   else:                                                               โ”‚
โ”‚ โฑ 84 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   raise e                                                         โ”‚
โ”‚   85 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   finally:                                                                โ”‚
โ”‚   86 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   if pbar:                                                            โ”‚
โ”‚   87 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   pbar.update(1)                                                  โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /data/source/langchain/langchain/document_loaders/directory.py:78 in load                        โ”‚
โ”‚                                                                                                  โ”‚
โ”‚   75 โ”‚   โ”‚   โ”‚   if i.is_file():                                                                 โ”‚
โ”‚   76 โ”‚   โ”‚   โ”‚   โ”‚   if _is_visible(i.relative_to(p)) or self.load_hidden:                       โ”‚
โ”‚   77 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   try:                                                                    โ”‚
โ”‚ โฑ 78 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   sub_docs = self.loader_cls(str(i), **self.loader_kwargs).load()     โ”‚
โ”‚   79 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   docs.extend(sub_docs)                                               โ”‚
โ”‚   80 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   except Exception as e:                                                  โ”‚
โ”‚   81 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   if self.silent_errors:                                              โ”‚
โ”‚                                                                                                  โ”‚
โ”‚ /data/source/langchain/langchain/document_loaders/text.py:44 in load                             โ”‚
โ”‚                                                                                                  โ”‚
โ”‚   41 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   except UnicodeDecodeError:                                          โ”‚
โ”‚   42 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   continue                                                        โ”‚
โ”‚   43 โ”‚   โ”‚   โ”‚   โ”‚   else:                                                                       โ”‚
โ”‚ โฑ 44 โ”‚   โ”‚   โ”‚   โ”‚   โ”‚   raise RuntimeError(f"Error loading {self.file_path}") from e            โ”‚
โ”‚   45 โ”‚   โ”‚   โ”‚   except Exception as e:                                                          โ”‚
โ”‚   46 โ”‚   โ”‚   โ”‚   โ”‚   raise RuntimeError(f"Error loading {self.file_path}") from e                โ”‚
โ”‚   47                                                                                             โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
RuntimeError: Error loading ../../../../../tests/integration_tests/examples/example-non-utf8.txt

The file example-non-utf8.txt uses a different encoding the load() function fails with a helpful message indicating which file failed decoding.

With the default behavior of TextLoader any failure to load any of the documents will fail the whole loading process and no documents are loaded.

B. Silent fail#

We can pass the parameter silent_errors to the DirectoryLoader to skip the files which could not be loaded and continue the load process.

loader = DirectoryLoader(path, glob="**/*.txt", loader_cls=TextLoader, silent_errors=True)
docs = loader.load()
Error loading ../../../../../tests/integration_tests/examples/example-non-utf8.txt
doc_sources = [doc.metadata['source']  for doc in docs]
doc_sources
['../../../../../tests/integration_tests/examples/whatsapp_chat.txt',
 '../../../../../tests/integration_tests/examples/example-utf8.txt']

C. Auto detect encodings#

We can also ask TextLoader to auto detect the file encoding before failing, by passing the autodetect_encoding to the loader class.

text_loader_kwargs={'autodetect_encoding': True}
loader = DirectoryLoader(path, glob="**/*.txt", loader_cls=TextLoader, loader_kwargs=text_loader_kwargs)
docs = loader.load()
doc_sources = [doc.metadata['source']  for doc in docs]
doc_sources
['../../../../../tests/integration_tests/examples/example-non-utf8.txt',
 '../../../../../tests/integration_tests/examples/whatsapp_chat.txt',
 '../../../../../tests/integration_tests/examples/example-utf8.txt']