You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/en/docs/advanced/advanced-dependencies.md
+88Lines changed: 88 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,3 +63,91 @@ In the chapters about security, there are utility functions that are implemented
63
63
If you understood all this, you already know how those utility tools for security work underneath.
64
64
65
65
///
66
+
67
+
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
68
+
69
+
/// warning
70
+
71
+
You most probably don't need these technical details.
72
+
73
+
These details are useful mainly if you had a FastAPI application older than 0.118.0 and you are facing issues with dependencies with `yield`.
74
+
75
+
///
76
+
77
+
Dependencies with `yield` have evolved over time to account for the different use cases and to fix some issues, here's a summary of what has changed.
78
+
79
+
### Dependencies with `yield` and `StreamingResponse`, Technical Details { #dependencies-with-yield-and-streamingresponse-technical-details }
80
+
81
+
Before FastAPI 0.118.0, if you used a dependency with `yield`, it would run the exit code after the *path operation function* returned but right before sending the response.
82
+
83
+
The intention was to avoid holding resources for longer than necessary, waiting for the response to travel through the network.
84
+
85
+
This change also meant that if you returned a `StreamingResponse`, the exit code of the dependency with `yield` would have been already run.
86
+
87
+
For example, if you had a database session in a dependency with `yield`, the `StreamingResponse` would not be able to use that session while streaming data because the session would have already been closed in the exit code after `yield`.
88
+
89
+
This behavior was reverted in 0.118.0, to make the exit code after `yield` be executed after the response is sent.
90
+
91
+
/// info
92
+
93
+
As you will see below, this is very similar to the behavior before version 0.106.0, but with several improvements and bug fixes for corner cases.
94
+
95
+
///
96
+
97
+
#### Use Cases with Early Exit Code { #use-cases-with-early-exit-code }
98
+
99
+
There are some use cases with specific conditions that could benefit from the old behavior of running the exit code of dependencies with `yield` before sending the response.
100
+
101
+
For example, imagine you have code that uses a database session in a dependency with `yield` only to verify a user, but the database session is never used again in the *path operation function*, only in the dependency, **and** the response takes a long time to be sent, like a `StreamingResponse` that sends data slowly, but for some reason doesn't use the database.
102
+
103
+
In this case, the database session would be held until the response is finished being sent, but if you don't use it, then it wouldn't be necessary to hold it.
That way the session would release the database connection, so other requests could use it.
124
+
125
+
If you have a different use case that needs to exit early from a dependency with `yield`, please create a <ahref="https://github.com/fastapi/fastapi/discussions/new?category=questions"class="external-link"target="_blank">GitHub Discussion Question</a> with your specific use case and why you would benefit from having early closing for dependencies with `yield`.
126
+
127
+
If there are compelling use cases for early closing in dependencies with `yield`, I would consider adding a new way to opt in to early closing.
128
+
129
+
### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details }
130
+
131
+
Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
132
+
133
+
This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
134
+
135
+
### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
136
+
137
+
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
138
+
139
+
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
140
+
141
+
This was changed in FastAPI 0.106.0 with the intention to not hold resources while waiting for the response to travel through the network.
142
+
143
+
/// tip
144
+
145
+
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
146
+
147
+
So, this way you will probably have cleaner code.
148
+
149
+
///
150
+
151
+
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`.
152
+
153
+
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.
@@ -51,7 +51,7 @@ You can use `async` or regular functions.
51
51
52
52
If you use a `try` block in a dependency with `yield`, you'll receive any exception that was thrown when using the dependency.
53
53
54
-
For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or create any other error, you will receive the exception in your dependency.
54
+
For example, if some code at some point in the middle, in another dependency or in a *path operation*, made a database transaction "rollback" or created any other exception, you would receive the exception in your dependency.
55
55
56
56
So, you can look for that specific exception inside the dependency with `except SomeException`.
57
57
@@ -95,9 +95,11 @@ This works thanks to Python's <a href="https://docs.python.org/3/library/context
95
95
96
96
## Dependencies with `yield` and `HTTPException` { #dependencies-with-yield-and-httpexception }
97
97
98
-
You saw that you can use dependencies with `yield` and have `try` blocks that catch exceptions.
98
+
You saw that you can use dependencies with `yield` and have `try` blocks that try to execute some code and then run some exit code after `finally`.
99
99
100
-
The same way, you could raise an `HTTPException` or similar in the exit code, after the `yield`.
100
+
You can also use `except` to catch the exception that was raised and do something with it.
101
+
102
+
For example, you can raise a different exception, like `HTTPException`.
101
103
102
104
/// tip
103
105
@@ -109,7 +111,7 @@ But it's there for you if you need it. π€
An alternative you could use to catch exceptions (and possibly also raise another `HTTPException`) is to create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
114
+
If you want to catch exceptions and create a custom response based on that, create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
113
115
114
116
## Dependencies with `yield` and `except` { #dependencies-with-yield-and-except }
115
117
@@ -121,7 +123,7 @@ In this case, the client will see an *HTTP 500 Internal Server Error* response a
121
123
122
124
### Always `raise` in Dependencies with `yield` and `except` { #always-raise-in-dependencies-with-yield-and-except }
123
125
124
-
If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, you should re-raise the original exception.
126
+
If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, **you should re-raise the original exception**.
125
127
126
128
You can re-raise the same exception using `raise`:
127
129
@@ -178,48 +180,15 @@ After one of those responses is sent, no other response can be sent.
178
180
179
181
/// tip
180
182
181
-
This diagram shows `HTTPException`, but you could also raise any other exception that you catch in a dependency with `yield` or with a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
182
-
183
-
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`. In most cases you will want to re-raise that same exception or a new one from the dependency with `yield` to make sure it's properly handled.
183
+
If you raise any exception in the code from the *path operation function*, it will be passed to the dependencies with yield, including `HTTPException`. In most cases you will want to re-raise that same exception or a new one from the dependency with `yield` to make sure it's properly handled.
184
184
185
185
///
186
186
187
187
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks { #dependencies-with-yield-httpexception-except-and-background-tasks }
188
188
189
-
/// warning
190
-
191
-
You most probably don't need these technical details, you can skip this section and continue below.
192
-
193
-
These details are useful mainly if you were using a version of FastAPI prior to 0.106.0 and used resources from dependencies with `yield` in background tasks.
194
-
195
-
///
196
-
197
-
### Dependencies with `yield` and `except`, Technical Details { #dependencies-with-yield-and-except-technical-details }
198
-
199
-
Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
200
-
201
-
This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
202
-
203
-
### Background Tasks and Dependencies with `yield`, Technical Details { #background-tasks-and-dependencies-with-yield-technical-details }
204
-
205
-
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
206
-
207
-
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.
208
-
209
-
Nevertheless, as this would mean waiting for the response to travel through the network while unnecessarily holding a resource in a dependency with yield (for example a database connection), this was changed in FastAPI 0.106.0.
210
-
211
-
/// tip
212
-
213
-
Additionally, a background task is normally an independent set of logic that should be handled separately, with its own resources (e.g. its own database connection).
214
-
215
-
So, this way you will probably have cleaner code.
216
-
217
-
///
218
-
219
-
If you used to rely on this behavior, now you should create the resources for background tasks inside the background task itself, and use internally only data that doesn't depend on the resources of dependencies with `yield`.
220
-
221
-
For example, instead of using the same database session, you would create a new database session inside of the background task, and you would obtain the objects from the database using this new session. And then instead of passing the object from the database as a parameter to the background task function, you would pass the ID of that object and then obtain the object again inside the background task function.
189
+
Dependencies with `yield` have evolved over time to cover different use cases and fix some issues.
222
190
191
+
If you want to see what has changed in different versions of FastAPI, you can read more about it in the advanced guide, in [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}.
223
192
## Context Managers { #context-managers }
224
193
225
194
### What are "Context Managers" { #what-are-context-managers }
0 commit comments