Skip to content
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

Compatibility with aiofiles #376

Open
hwong557 opened this issue Nov 2, 2023 · 1 comment
Open

Compatibility with aiofiles #376

hwong557 opened this issue Nov 2, 2023 · 1 comment

Comments

@hwong557
Copy link

hwong557 commented Nov 2, 2023

aiofiles is a Python project to perform IO asynchronously. I am able to asynchronously read files from s3, but I cannot write files to s3. The following code example fails:

import asyncio

import aiofiles
import aiohttp
from cloudpathlib import S3Path


async def main():
    chunk_size = 1000

    path = S3Path("s3://my-bucket/image.png")

    async with aiohttp.ClientSession() as session:
        async with session.get("http://httpbin.org/image/png") as resp:
            async with aiofiles.open(path, "wb") as f:
                async for chunk in resp.content.iter_chunked(chunk_size):
                    await f.write(chunk)


asyncio.run(main())

The error is:

FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpq4ls9jhw/....../image.png'

I am using cloudpathlib==0.16.0 and aiofiles==23.2.1.

If I add a path.touch() before initializing the ClientSession, the code runs without error, but the file in s3 is zero bytes.

Thank you for your work on such a clean and easy to use library! It truly is a joy!

@hwong557 hwong557 changed the title Compatability with aiofiles Compatibility with aiofiles Nov 2, 2023
@pjbull
Copy link
Member

pjbull commented Nov 2, 2023

Thanks @hwong557, the issue here depends entirely on what aiofiles.open(path, "wb") does within their method with the S3Path object. This is another instance of the kinds of issues in #128.

If they see that path has an open method and they use that properly like a context manager, things could work. If not, all bets are off. I took a look, and they just pass it to the built-in open.

A few possible workaround:

  • It's possible that the experimental work in WIP: Patch open, os and os.path builtins #322 makes this scenario work. That would be useful to know.
  • Write to a temporary file and then use your cloud path's upload_from method to write to the cloud.
  • Call path.open() before your async code and then path.close() afterwards to close and upload it (this likely breaks the async writing, but I'm not sure).
  • Maybe aiofiles is willing to fix their library to be compatible with pathlike objects that provide open methods to call that instead of using the built-in open method assuming that everything is a filepath.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants