Different file formats require user to know if file should be opened binary or not
- Dominant language
- Python
- Stars
- 4.8k
- Forks
- 617
- PR merge metrics
- No merged PRs in 30d
Description
From the docs, I think this is working as designed, but wanted to check. There's a decent chance I'm doing something wrong.
File auto-detection becomes less useful to library consumer like me if I have to check the type of file I'm using and take different branches for it. It's still great to get a normalized representation of various formats . . . thanks for that.
If you open an Excel file (.xlsx) with just mode `r`, you get an error `zipfile.BadZipFile: File is not a zip file`. Doesn't matter if I specify the format in the second parameter to `load()` when calling `open()` myself. You must specify mode `rb`.
This in on Ubuntu 20.04, python3.9, openpyxl 3.0.9
```python
# zipfile.BadZipFile: File is not a zip file
with open("mySheet.xlsx", "r") as fh:
data.load(fh)
# OK
with open("mySheet.xlsx", "rb") as fh:
data.load(fh)
```
If you pass the file path, it cannot determine the file type. If you specify the type, it doesn't open binary.
```python
# zipfile.BadZipFile: File is not a zip file
data.load("mySheet.xlsx", "xlsx")
# tablib.exceptions.UnsupportedFormat: Tablib has no format 'None' or it is not registered.
data.load("mySheet.xlsx")
```
I think the issue in `data.load("mySheet.xlsx", "xlsx")` is because `core.normalize_input()` converts the path given as a str to a StringIO. And when openpyxl passes it to zipfile, zipfile would call `open()` with mode `rb` if it was still a string. I'm not sure zipfile is ready for StringIO at all. It hits this code block which doesn't seem to expect a StringIO: https://github.com/python/cpython/blob/main/Lib/zipfile.py#L1273
Now if I shift to CSV, I can't use mode `rb`. It does give instructions in the exception if you give it the file type hint. And it does get it right if you leave the call to `open()` to tablib and give it the format hint.
```python
# tablib.exceptions.UnsupportedFormat: Tablib has no format 'None' or it is not registered.
with open("myCsv.csv", "rb") as fh:
data.load(fh)
# _csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)
with open("myCsv.csv", "rb") as fh:
data.load(fh, "csv")
# tablib.exceptions.UnsupportedFormat: Tablib has no format 'None' or it is not registered.
data.load("myCsv.csv")
# OK
data.load("myCsv.csv", "csv")
```
Contributor guide
Assessment
This issue has not been assessed yet.