# File.open to support different encodings

**URL:** <https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491>\
**Category:** Django Internals\
**Created:** [June 9, 2023, 9:48pm UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491 "2023-06-09T21:48:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![liori](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/liori/32/14134_2.png) [@liori](https://forum.djangoproject.com/u/liori)\
**Post date:** [June 9, 2023, 9:48pm UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/1 "2023-06-09T21:48:07Z")

</div>

Currently the [​File.open](https://github.com/django/django/blob/main/django/core/files/base.py#L108) method has only a single parameter `mode`. `mode` can be set to suggest opening a file in text mode. Then, Python’s `open` will by default attempt to use the common utf-8 encoding.

It is a common pattern in a code base I work on to use the `utf-8-sig` encoding for CSV files, as this provides a slight improvement to user experience when opening the file in Excel. Right now, to create a file in this encoding using Django’s File, we have to open it in a binary mode and explicitly wrap the file handle in a codec. It would be helpful if, just like the base Python’s `open` function, `File.open` also accepted an `encoding` parameter, and pass it to the Python’s `open` function.

I believe that this kind of enhancement is natural, as Python developers are used to `open` allowing to set encoding, especially in Python 3. Actually, I was a bit surprised not seeing it already implemented.

I’ve opened [a ticket](https://code.djangoproject.com/ticket/34642) about this issue and I am willing to work on this feature if there is chance of it being merged.

David Sanders has suggested in the ticket to have a full `*args, **kwargs` being allowed and passed directly to `open`. I admit though I personally like being explicit in the offered API—especially as it wouldn’t be that easy to later reproduce the full scope of such API in libraries like django-storages. And so I would focus only on `encoding`.

---

<div class="post-metadata">

**Author:** ![Lily-Foote](https://avatars.discourse-cdn.com/v4/letter/l/c37758/32.png) [@Lily-Foote](https://forum.djangoproject.com/u/Lily-Foote)\
**Post date:** [June 9, 2023, 11:04pm UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/2 "2023-06-09T23:04:57Z")

</div>

I think it makes sense to match the api of `open` where possible.

---

<div class="post-metadata">

**Author:** ![carltongibson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/carltongibson/32/267_2.png) [@carltongibson](https://forum.djangoproject.com/u/carltongibson)\
**Post date:** [June 10, 2023, 12:42pm UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/3 "2023-06-10T12:42:05Z")

</div>

My only concern here is adding API that all users need to understand and decide about when only a very small subset will ever use it.

What does the wrapping in a codec actually look like? Is that really too much to bare for a rarely needed option?

Not sure.

---

<div class="post-metadata">

**Author:** ![liori](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/liori/32/14134_2.png) [@liori](https://forum.djangoproject.com/u/liori)\
**Post date:** [June 11, 2023, 3:28pm UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/4 "2023-06-11T15:28:01Z")

</div>

> [@carltongibson](#):
>
> What does the wrapping in a codec actually look like? Is that really too much to bare for a rarely needed option?

```auto
with some_django_file.open("wb") as fh:
    encoded_fh = io.TextIOWrapper(fh, encoding="utf-8-sig")
    … use encoded_fh instead of fh …
    encoded_fh.flush()

```

There are two risks associated with this piece of code: (1) someone accidentally uses `fh`, as opposed to `encoded_fh`. (2) flush() is forgotten. Mitigation by creating a custom helper context manager also has a drawback of developers forgetting about its existence and using raw Django’s File.open instead.

> [@carltongibson](#):
>
> My only concern here is adding API that all users need to understand and decide about when only a very small subset will ever use it.

I wonder how many users of Python’s `open` function use the `encoding` argument. Obviously Python has more developers than Django, but the standard library is also larger. Still, when we are writing Python code outside of Django, we take this feature for granted.

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [June 12, 2023, 7:28am UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/5 "2023-06-12T07:28:10Z")

</div>

+1 from me.

> [@carltongibson](#):
>
> My only concern here is adding API that all users need to understand and decide about when only a very small subset will ever use it.

I think matching the `open` builtin is more important than expanding the API surface area. It’s like how [`pathlib.Path.open`](https://docs.python.org/3.11/library/pathlib.html#pathlib.Path.open) supports the full `open` signature.

Plus, seeing the argument may be a small reminder that not all text files use UTF-8.

---

<div class="post-metadata">

**Author:** ![carltongibson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/carltongibson/32/267_2.png) [@carltongibson](https://forum.djangoproject.com/u/carltongibson)\
**Post date:** [June 12, 2023, 7:43am UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/6 "2023-06-12T07:43:04Z")

</div>

Yep, OK. +1 (just for clarity)

---

<div class="post-metadata">

**Author:** ![nessita](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/nessita/32/12194_2.png) [@nessita](https://forum.djangoproject.com/u/nessita)\
**Post date:** [June 19, 2023, 1:03pm UTC](https://forum.djangoproject.com/t/file-open-to-support-different-encodings/21491/7 "2023-06-19T13:03:07Z")

</div>

I’m also +1 on this, and I would second the proposal in the ticket where it’s suggested to pass `*args` and `**kwargs` to `open` to avoid gatekeeping.
