-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FileResponse works with files asynchronously #3476
FileResponse works with files asynchronously #3476
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filepath.stat()
and filepath.open()
in def prepare()
can block too.
Please run them in an executor as well.
Codecov Report
@@ Coverage Diff @@
## master #3476 +/- ##
==========================================
+ Coverage 97.93% 97.93% +<.01%
==========================================
Files 44 44
Lines 8559 8561 +2
Branches 1383 1383
==========================================
+ Hits 8382 8384 +2
Misses 74 74
Partials 103 103
Continue to review full report at Codecov.
|
thanks! |
* FileResponse works with files asynchronously * FileResponse: the 'prepare' method works with files asynchronously
@@ -334,8 +337,8 @@ def __init__(self, path: Union[str, pathlib.Path], | |||
self.headers[hdrs.CONTENT_RANGE] = 'bytes {0}-{1}/{2}'.format( | |||
real_start, real_start + count - 1, file_size) | |||
|
|||
with filepath.open('rb') as fobj: | |||
with (await loop.run_in_executor(None, filepath.open, 'rb')) as fobj: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Tolmachofof blocking close of the fobj
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aamalev thanks for your comment!
I think that something like _FileContextManager
would solve this problem.
Simplified example:
class _FileContextManager:
def __init__(self, filepath, flags, start):
self._filepath = filepath
self._flags = flags
self._start = start
self._fobj = None
async def __aenter__(self):
loop = asyncio.get_event_loop()
self._fobj = await loop.run_in_executor(
None, self._open, self._filepath, self._start
)
return self._fobj
def _open(self, filepath, start):
fobj = filepath.open(self._flags)
if start:
fobj.seek(start)
return fobj
async def __aexit__(self, exc_type, exc_val, exc_tb):
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, self._fobj.close)
self._fobj = None
If this acceptable i can make a PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the conversion with
to try..finally
is more suitable. _FileContextManager
need members loop and executor, and this is too much for a one-time code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. try..finally
statement sounds good. I will make a PR.
What do these changes do?
The web FileResponse works with files asynchronously
Are there changes in behavior for the user?
No
Related issue number
#3313
Checklist
CONTRIBUTORS.txt
CHANGES
folder<issue_id>.<type>
for example (588.bugfix)issue_id
change it to the pr id after creating the pr.feature
: Signifying a new feature..bugfix
: Signifying a bug fix..doc
: Signifying a documentation improvement..removal
: Signifying a deprecation or removal of public API..misc
: A ticket has been closed, but it is not of interest to users.