0
# importlib_resources
1
2
A backport of the standard library's importlib.resources module providing enhanced resource access capabilities for Python packages. This library enables reliable access to package resources such as data files, templates, configuration files, and other assets bundled with Python packages in a cross-platform, version-agnostic manner.
3
4
## Package Information
5
6
- **Package Name**: importlib_resources
7
- **Language**: Python
8
- **Installation**: `pip install importlib_resources`
9
10
## Core Imports
11
12
```python
13
import importlib_resources
14
```
15
16
Most common imports for resource access:
17
18
```python
19
from importlib_resources import files, as_file, read_text, read_binary
20
```
21
22
For functional API:
23
24
```python
25
from importlib_resources import (
26
open_text, open_binary, read_text, read_binary,
27
path, contents, is_resource
28
)
29
```
30
31
For abstract base classes and protocols:
32
33
```python
34
from importlib_resources.abc import ResourceReader, Traversable, TraversableResources, TraversalError
35
```
36
37
For reader implementations:
38
39
```python
40
from importlib_resources.readers import FileReader, ZipReader, NamespaceReader, MultiplexedPath
41
```
42
43
For simple reader interface:
44
45
```python
46
from importlib_resources.simple import SimpleReader, ResourceContainer, ResourceHandle, TraversableReader
47
```
48
49
## Basic Usage
50
51
```python
52
import importlib_resources
53
from importlib_resources import files, as_file, read_text
54
55
# Access package resources using files() - recommended approach
56
resource_dir = files('mypackage.data')
57
config_file = resource_dir / 'config.json'
58
59
# Read resource content directly
60
content = config_file.read_text()
61
62
# Get actual file system path using context manager
63
with as_file(config_file) as path:
64
# Use path as regular file system path
65
with open(path) as f:
66
data = f.read()
67
68
# Functional API - alternative approach
69
text_content = read_text('mypackage.data', 'readme.txt')
70
binary_content = read_binary('mypackage.data', 'image.png')
71
72
# Check if resource exists
73
from importlib_resources import is_resource
74
if is_resource('mypackage.data', 'config.json'):
75
config = read_text('mypackage.data', 'config.json')
76
```
77
78
## Architecture
79
80
importlib_resources provides a layered architecture for accessing package resources:
81
82
- **Traversable Interface**: Modern path-like API (`files()`, `as_file()`) providing filesystem-like navigation
83
- **Resource Readers**: Backend implementations (`FileReader`, `ZipReader`, `NamespaceReader`) that handle different package storage formats
84
- **Functional API**: Legacy functions (`read_text`, `open_binary`, etc.) for backward compatibility
85
- **Adapter Layer**: Compatibility adapters that bridge different Python versions and loader implementations
86
- **Simple Reader Protocol**: Low-level interface (`SimpleReader`) for implementing custom resource providers
87
88
This design enables transparent access to resources whether packages are installed as directories, zip files, or namespace packages, while providing both modern and legacy APIs for different use cases.
89
90
## Capabilities
91
92
### Resource Discovery and Navigation
93
94
Core functions for discovering and navigating package resources using the modern Traversable interface.
95
96
```python { .api }
97
def files(anchor: Optional[Anchor] = None) -> Traversable:
98
"""
99
Get a Traversable resource for an anchor.
100
101
Parameters:
102
- anchor: Union[types.ModuleType, str, None] - Package as module object, string name, or None to infer from caller
103
104
Returns:
105
Traversable: Object for navigating package resources
106
"""
107
```
108
109
```python { .api }
110
def as_file(path) -> ContextManager:
111
"""
112
Given a Traversable object, return that object as a path on the local file system in a context manager.
113
114
Parameters:
115
- path: Traversable object representing a resource
116
117
Returns:
118
ContextManager yielding pathlib.Path: Temporary path to resource on file system
119
"""
120
```
121
122
### Resource Reading Functions
123
124
Functional API for directly reading resource content with simplified parameter handling.
125
126
```python { .api }
127
def read_text(anchor, *path_names, encoding=_MISSING, errors='strict') -> str:
128
"""
129
Read and return contents of resource within package as str.
130
131
Parameters:
132
- anchor: Union[types.ModuleType, str] - Package as module object or string name
133
- path_names: Variable path components to resource file
134
- encoding: str - Text encoding (default: 'utf-8')
135
- errors: str - Error handling mode (default: 'strict')
136
137
Returns:
138
str: Resource content as text
139
"""
140
```
141
142
```python { .api }
143
def read_binary(anchor, *path_names) -> bytes:
144
"""
145
Read and return contents of resource within package as bytes.
146
147
Parameters:
148
- anchor: Union[types.ModuleType, str] - Package as module object or string name
149
- path_names: Variable path components to resource file
150
151
Returns:
152
bytes: Resource content as binary data
153
"""
154
```
155
156
### Resource Opening Functions
157
158
Functions for opening resources with file-like objects for streaming access.
159
160
```python { .api }
161
def open_text(anchor, *path_names, encoding=_MISSING, errors='strict') -> TextIO:
162
"""
163
Open for text reading the resource within package.
164
165
Parameters:
166
- anchor: Union[types.ModuleType, str] - Package as module object or string name
167
- path_names: Variable path components to resource file
168
- encoding: str - Text encoding (default: 'utf-8', required when using multiple path_names)
169
- errors: str - Error handling mode (default: 'strict')
170
171
Returns:
172
TextIO: Text file-like object for reading
173
"""
174
```
175
176
```python { .api }
177
def open_binary(anchor, *path_names) -> BinaryIO:
178
"""
179
Open for binary reading the resource within package.
180
181
Parameters:
182
- anchor: Union[types.ModuleType, str] - Package as module object or string name
183
- path_names: Variable path components to resource file
184
185
Returns:
186
BinaryIO: Binary file-like object for reading
187
"""
188
```
189
190
### Resource Path Access
191
192
Functions for accessing resources as file system paths.
193
194
```python { .api }
195
def path(anchor, *path_names) -> ContextManager:
196
"""
197
Return the path to the resource as an actual file system path.
198
199
Parameters:
200
- anchor: Union[types.ModuleType, str] - Package as module object or string name
201
- path_names: Variable path components to resource file
202
203
Returns:
204
ContextManager yielding pathlib.Path: Temporary path to resource
205
"""
206
```
207
208
### Resource Validation and Discovery
209
210
Functions for checking resource existence and listing package contents.
211
212
```python { .api }
213
def is_resource(anchor, *path_names) -> bool:
214
"""
215
Return True if there is a resource at the specified path within the package.
216
217
Parameters:
218
- anchor: Union[types.ModuleType, str] - Package as module object or string name
219
- path_names: Variable path components to resource
220
221
Returns:
222
bool: True if resource exists and is a file
223
"""
224
```
225
226
```python { .api }
227
def contents(anchor, *path_names) -> Iterator[str]:
228
"""
229
Return an iterable over the named resources within the package.
230
231
DEPRECATED: Use files(anchor).iterdir() instead.
232
233
Parameters:
234
- anchor: Union[types.ModuleType, str] - Package as module object or string name
235
- path_names: Variable path components to directory
236
237
Returns:
238
Iterator[str]: Names of resources in the directory
239
"""
240
```
241
242
## Abstract Base Classes and Protocols
243
244
### ResourceReader
245
246
Abstract base class for implementing custom resource readers.
247
248
```python { .api }
249
class ResourceReader(metaclass=abc.ABCMeta):
250
"""Abstract base class for loaders to provide resource reading support."""
251
252
@abc.abstractmethod
253
def open_resource(self, resource: Text) -> BinaryIO:
254
"""
255
Return an opened, file-like object for binary reading.
256
257
The 'resource' argument is expected to represent only a file name.
258
If the resource cannot be found, FileNotFoundError is raised.
259
260
Parameters:
261
- resource: Text - Resource file name
262
263
Returns:
264
BinaryIO: Binary file-like object
265
266
Raises:
267
FileNotFoundError: If resource cannot be found
268
"""
269
270
@abc.abstractmethod
271
def resource_path(self, resource: Text) -> Text:
272
"""
273
Return the file system path to the specified resource.
274
275
The 'resource' argument is expected to represent only a file name.
276
If the resource does not exist on the file system, raise FileNotFoundError.
277
278
Parameters:
279
- resource: Text - Resource file name
280
281
Returns:
282
Text: File system path to resource
283
284
Raises:
285
FileNotFoundError: If resource does not exist on file system
286
"""
287
288
@abc.abstractmethod
289
def is_resource(self, path: Text) -> bool:
290
"""
291
Return True if the named 'path' is a resource.
292
293
Files are resources, directories are not.
294
295
Parameters:
296
- path: Text - Resource path
297
298
Returns:
299
bool: True if path is a resource (file), False for directories
300
"""
301
302
@abc.abstractmethod
303
def contents(self) -> Iterable[str]:
304
"""
305
Return an iterable of entries in `package`.
306
307
Returns:
308
Iterable[str]: Resource names
309
"""
310
```
311
312
### Traversable Protocol
313
314
Protocol defining path-like interface for resource navigation.
315
316
```python { .api }
317
class Traversable(Protocol):
318
"""
319
An object with a subset of pathlib.Path methods suitable for traversing directories and opening files.
320
"""
321
322
@abc.abstractmethod
323
def iterdir(self) -> Iterator["Traversable"]:
324
"""
325
Yield Traversable objects in self.
326
327
Returns:
328
Iterator[Traversable]: Child resources
329
"""
330
331
def read_bytes(self) -> bytes:
332
"""
333
Read contents of self as bytes.
334
335
Returns:
336
bytes: Resource content as binary data
337
"""
338
339
def read_text(self, encoding: Optional[str] = None, errors: Optional[str] = None) -> str:
340
"""
341
Read contents of self as text.
342
343
Parameters:
344
- encoding: Optional[str] - Text encoding
345
- errors: Optional[str] - Error handling mode
346
347
Returns:
348
str: Resource content as text
349
"""
350
351
@abc.abstractmethod
352
def is_dir(self) -> bool:
353
"""
354
Return True if self is a directory.
355
356
Returns:
357
bool: True if directory
358
"""
359
360
@abc.abstractmethod
361
def is_file(self) -> bool:
362
"""
363
Return True if self is a file.
364
365
Returns:
366
bool: True if file
367
"""
368
369
def joinpath(self, *descendants: Union[str, os.PathLike[str]]) -> "Traversable":
370
"""
371
Return Traversable resolved with any descendants applied.
372
373
Parameters:
374
- descendants: Variable path segments relative to self
375
376
Returns:
377
Traversable: Resource at joined path
378
379
Raises:
380
TraversalError: If target not found during traversal
381
"""
382
383
def __truediv__(self, child: Union[str, os.PathLike[str]]) -> "Traversable":
384
"""
385
Return Traversable child in self.
386
387
Parameters:
388
- child: Path segment for child resource
389
390
Returns:
391
Traversable: Child resource
392
"""
393
394
@overload
395
def open(self, mode: Literal['r'] = 'r', *args: Any, **kwargs: Any) -> TextIO: ...
396
397
@overload
398
def open(self, mode: Literal['rb'], *args: Any, **kwargs: Any) -> BinaryIO: ...
399
400
@abc.abstractmethod
401
def open(self, mode: str = 'r', *args: Any, **kwargs: Any) -> Union[TextIO, BinaryIO]:
402
"""
403
Open resource for reading.
404
405
Parameters:
406
- mode: str - Open mode ('r' for text, 'rb' for binary)
407
- args, kwargs: Additional arguments for opening
408
409
Returns:
410
Union[TextIO, BinaryIO]: File-like object
411
"""
412
413
@property
414
@abc.abstractmethod
415
def name(self) -> str:
416
"""
417
The base name of this object without any parent references.
418
419
Returns:
420
str: Resource name
421
"""
422
```
423
424
### TraversableResources
425
426
Extended ResourceReader that provides traversable access to resources.
427
428
```python { .api }
429
class TraversableResources(ResourceReader):
430
"""
431
The required interface for providing traversable resources.
432
"""
433
434
@abc.abstractmethod
435
def files(self) -> "Traversable":
436
"""
437
Return a Traversable object for the loaded package.
438
439
Returns:
440
Traversable: Root traversable for package resources
441
"""
442
```
443
444
## Resource Reader Implementations
445
446
### FileReader
447
448
Reader for package resources stored as regular files on the filesystem.
449
450
```python { .api }
451
class FileReader(TraversableResources):
452
"""
453
Reader for package resources stored as regular files on the filesystem.
454
"""
455
456
def __init__(self, loader):
457
"""
458
Initialize with a loader that has a path attribute.
459
460
Parameters:
461
- loader: Loader object with path attribute pointing to package directory
462
"""
463
464
def resource_path(self, resource: str) -> str:
465
"""
466
Return the file system path to prevent resources.path() from creating a temporary copy.
467
468
Parameters:
469
- resource: str - Resource file name
470
471
Returns:
472
str: Absolute path to resource on filesystem
473
"""
474
475
def files(self) -> Traversable:
476
"""
477
Return a Traversable object for the package directory.
478
479
Returns:
480
Traversable: Path object for the package directory
481
"""
482
```
483
484
### ZipReader
485
486
Reader for package resources stored within zip files.
487
488
```python { .api }
489
class ZipReader(TraversableResources):
490
"""
491
Reader for package resources stored within zip files.
492
"""
493
494
def __init__(self, loader, module: str):
495
"""
496
Initialize with a zip loader and module name.
497
498
Parameters:
499
- loader: Zip loader with archive and prefix attributes
500
- module: str - Module name for the package
501
"""
502
503
def open_resource(self, resource: str) -> BinaryIO:
504
"""
505
Return an opened, file-like object for binary reading.
506
507
Parameters:
508
- resource: str - Resource file name
509
510
Returns:
511
BinaryIO: Binary file-like object
512
513
Raises:
514
FileNotFoundError: If resource cannot be found
515
"""
516
517
def is_resource(self, path: str) -> bool:
518
"""
519
Return True if the named path is a resource (workaround for zipfile issues).
520
521
Parameters:
522
- path: str - Resource path
523
524
Returns:
525
bool: True if path is a resource and exists
526
"""
527
528
def files(self) -> Traversable:
529
"""
530
Return a Traversable object for the zip package.
531
532
Returns:
533
Traversable: ZipPath object for navigating zip contents
534
"""
535
```
536
537
### NamespaceReader
538
539
Reader for namespace packages that may span multiple directories.
540
541
```python { .api }
542
class NamespaceReader(TraversableResources):
543
"""
544
Reader for namespace packages that may span multiple directories.
545
"""
546
547
def __init__(self, namespace_path):
548
"""
549
Initialize with a namespace path.
550
551
Parameters:
552
- namespace_path: NamespacePath object with multiple locations
553
554
Raises:
555
ValueError: If path is not a valid namespace path
556
"""
557
558
def resource_path(self, resource: str) -> str:
559
"""
560
Return the file system path to prevent resources.path() from creating a temporary copy.
561
562
Parameters:
563
- resource: str - Resource file name
564
565
Returns:
566
str: Path to resource
567
"""
568
569
def files(self) -> Traversable:
570
"""
571
Return a MultiplexedPath for the namespace package.
572
573
Returns:
574
Traversable: MultiplexedPath spanning all namespace locations
575
"""
576
```
577
578
### MultiplexedPath
579
580
Traversable implementation that merges multiple paths for namespace packages.
581
582
```python { .api }
583
class MultiplexedPath(Traversable):
584
"""
585
Given a series of Traversable objects, implement a merged version of the interface across all objects.
586
Useful for namespace packages which may be multihomed at a single name.
587
"""
588
589
def __init__(self, *paths: Traversable):
590
"""
591
Initialize with multiple Traversable paths.
592
593
Parameters:
594
- paths: Variable number of Traversable objects to merge
595
596
Raises:
597
FileNotFoundError: If no paths provided
598
NotADirectoryError: If any path is not a directory
599
"""
600
601
def iterdir(self) -> Iterator[Traversable]:
602
"""
603
Yield Traversable objects in self, merging children from all paths.
604
605
Returns:
606
Iterator[Traversable]: Merged children from all paths
607
"""
608
609
def is_dir(self) -> bool:
610
"""
611
Return True (MultiplexedPath represents directories only).
612
613
Returns:
614
bool: Always True
615
"""
616
617
def is_file(self) -> bool:
618
"""
619
Return False (MultiplexedPath represents directories only).
620
621
Returns:
622
bool: Always False
623
"""
624
625
def joinpath(self, *descendants: StrPath) -> Traversable:
626
"""
627
Return Traversable resolved with any descendants applied.
628
629
Parameters:
630
- descendants: Variable path segments relative to self
631
632
Returns:
633
Traversable: Resource at joined path
634
"""
635
636
def open(self, *args, **kwargs):
637
"""
638
Raise FileNotFoundError (directories cannot be opened).
639
640
Raises:
641
FileNotFoundError: Always raised
642
"""
643
644
@property
645
def name(self) -> str:
646
"""
647
The base name of this object.
648
649
Returns:
650
str: Name from first path
651
"""
652
```
653
654
## Simple Reader Interface
655
656
### SimpleReader
657
658
The minimum, low-level interface required from a resource provider.
659
660
```python { .api }
661
class SimpleReader(metaclass=abc.ABCMeta):
662
"""
663
The minimum, low-level interface required from a resource provider.
664
"""
665
666
@property
667
@abc.abstractmethod
668
def package(self) -> str:
669
"""
670
The name of the package for which this reader loads resources.
671
672
Returns:
673
str: Package name
674
"""
675
676
@abc.abstractmethod
677
def children(self) -> List[SimpleReader]:
678
"""
679
Obtain an iterable of SimpleReader for available child containers (e.g. directories).
680
681
Returns:
682
List[SimpleReader]: Child readers for subdirectories
683
"""
684
685
@abc.abstractmethod
686
def resources(self) -> List[str]:
687
"""
688
Obtain available named resources for this virtual package.
689
690
Returns:
691
List[str]: Resource file names
692
"""
693
694
@abc.abstractmethod
695
def open_binary(self, resource: str) -> BinaryIO:
696
"""
697
Obtain a File-like for a named resource.
698
699
Parameters:
700
- resource: str - Resource file name
701
702
Returns:
703
BinaryIO: Binary file-like object for the resource
704
"""
705
706
@property
707
def name(self) -> str:
708
"""
709
The base name of the package.
710
711
Returns:
712
str: Last component of package name
713
"""
714
```
715
716
### ResourceContainer
717
718
Traversable container for a package's resources via its reader.
719
720
```python { .api }
721
class ResourceContainer(Traversable):
722
"""
723
Traversable container for a package's resources via its reader.
724
"""
725
726
def __init__(self, reader: SimpleReader):
727
"""
728
Initialize with a SimpleReader.
729
730
Parameters:
731
- reader: SimpleReader instance
732
"""
733
734
def is_dir(self) -> bool:
735
"""
736
Return True (containers are directories).
737
738
Returns:
739
bool: Always True
740
"""
741
742
def is_file(self) -> bool:
743
"""
744
Return False (containers are directories).
745
746
Returns:
747
bool: Always False
748
"""
749
750
def iterdir(self) -> Iterator[Traversable]:
751
"""
752
Yield Traversable objects in self.
753
754
Returns:
755
Iterator[Traversable]: Child resources and containers
756
"""
757
758
def open(self, *args, **kwargs):
759
"""
760
Raise IsADirectoryError (directories cannot be opened).
761
762
Raises:
763
IsADirectoryError: Always raised
764
"""
765
```
766
767
### ResourceHandle
768
769
Handle to a named resource in a ResourceReader.
770
771
```python { .api }
772
class ResourceHandle(Traversable):
773
"""
774
Handle to a named resource in a ResourceReader.
775
"""
776
777
def __init__(self, parent: ResourceContainer, name: str):
778
"""
779
Initialize with parent container and resource name.
780
781
Parameters:
782
- parent: ResourceContainer that contains this resource
783
- name: str - Resource file name
784
"""
785
786
def is_file(self) -> bool:
787
"""
788
Return True (handles represent files).
789
790
Returns:
791
bool: Always True
792
"""
793
794
def is_dir(self) -> bool:
795
"""
796
Return False (handles represent files).
797
798
Returns:
799
bool: Always False
800
"""
801
802
def open(self, mode: str = 'r', *args, **kwargs) -> Union[TextIO, BinaryIO]:
803
"""
804
Open the resource for reading.
805
806
Parameters:
807
- mode: str - Open mode ('r' for text, 'rb' for binary)
808
- args, kwargs: Additional arguments for text mode
809
810
Returns:
811
Union[TextIO, BinaryIO]: File-like object
812
"""
813
814
def joinpath(self, name: str):
815
"""
816
Raise RuntimeError (cannot traverse into a resource).
817
818
Raises:
819
RuntimeError: Always raised
820
"""
821
```
822
823
### TraversableReader
824
825
A TraversableResources based on SimpleReader.
826
827
```python { .api }
828
class TraversableReader(TraversableResources, SimpleReader):
829
"""
830
A TraversableResources based on SimpleReader. Resource providers may derive from this class
831
to provide the TraversableResources interface by supplying the SimpleReader interface.
832
"""
833
834
def files(self) -> Traversable:
835
"""
836
Return a ResourceContainer for this reader.
837
838
Returns:
839
Traversable: ResourceContainer wrapping this reader
840
"""
841
```
842
843
## Types
844
845
```python { .api }
846
from typing import (
847
Any, BinaryIO, Iterable, Iterator, List, Literal, NoReturn,
848
Optional, Protocol, Text, TextIO, Union, overload, runtime_checkable
849
)
850
import types
851
import os
852
import abc
853
854
Package = Union[types.ModuleType, str]
855
Anchor = Package
856
StrPath = Union[str, os.PathLike[str]]
857
Text = str # For compatibility with typing in source code
858
_MISSING = object() # Sentinel for default encoding parameter
859
```
860
861
```python { .api }
862
class TraversalError(Exception):
863
"""Exception raised during traversal operations when target cannot be found."""
864
pass
865
```
866
867
## Usage Examples
868
869
### Working with Package Data Files
870
871
```python
872
from importlib_resources import files, as_file
873
import json
874
875
# Access data files in your package
876
data_dir = files('mypackage.data')
877
config_file = data_dir / 'config.json'
878
879
# Read JSON configuration
880
config_data = json.loads(config_file.read_text())
881
882
# Work with binary data
883
image_file = data_dir / 'logo.png'
884
with as_file(image_file) as temp_path:
885
# Use with libraries that need file paths
886
from PIL import Image
887
img = Image.open(temp_path)
888
```
889
890
### Template and Asset Management
891
892
```python
893
from importlib_resources import files
894
import jinja2
895
896
# Access template files
897
templates_dir = files('myapp.templates')
898
template_file = templates_dir / 'email.html'
899
900
# Use with template engines
901
template_content = template_file.read_text()
902
template = jinja2.Template(template_content)
903
```
904
905
### Resource Iteration and Discovery
906
907
```python
908
from importlib_resources import files
909
910
# List all resources in a package directory
911
resource_dir = files('mypackage.resources')
912
for resource in resource_dir.iterdir():
913
if resource.is_file():
914
print(f"Found resource: {resource.name}")
915
# Process each resource
916
content = resource.read_text()
917
```
918
919
### Legacy Functional API Usage
920
921
```python
922
from importlib_resources import read_text, is_resource, path
923
924
# Check if resource exists before accessing
925
if is_resource('mypackage.data', 'settings.ini'):
926
settings = read_text('mypackage.data', 'settings.ini')
927
928
# Access nested resources
929
config = read_text('mypackage.config', 'production', 'database.yaml')
930
931
# Get temporary file path for external tools
932
with path('mypackage.data', 'input.csv') as csv_path:
933
# Use with pandas or other libraries requiring file paths
934
import pandas as pd
935
df = pd.read_csv(csv_path)
936
```
937
938
### Working with Different Reader Types
939
940
```python
941
from importlib_resources.readers import FileReader, ZipReader, NamespaceReader
942
943
# For packages installed as directories
944
file_reader = FileReader(some_loader)
945
files = file_reader.files()
946
947
# For packages in zip files
948
zip_reader = ZipReader(zip_loader, 'mypackage')
949
zip_files = zip_reader.files()
950
951
# For namespace packages
952
namespace_reader = NamespaceReader(namespace_path)
953
namespace_files = namespace_reader.files()
954
```
955
956
### Implementing Custom Resource Readers
957
958
```python
959
from importlib_resources.simple import SimpleReader, TraversableReader
960
from typing import List, BinaryIO
961
962
class CustomReader(TraversableReader):
963
"""Custom resource reader implementation."""
964
965
@property
966
def package(self) -> str:
967
return "mypackage"
968
969
def children(self) -> List[SimpleReader]:
970
return [] # Return child readers for subdirectories
971
972
def resources(self) -> List[str]:
973
return ["config.json", "data.txt"] # Return available resources
974
975
def open_binary(self, resource: str) -> BinaryIO:
976
# Return binary file-like object for the resource
977
return open(f"/path/to/{resource}", "rb")
978
979
# Use the custom reader
980
reader = CustomReader()
981
files = reader.files()
982
```