Python 3.8 treats "open" as imported openpyxl method instead of built-in function

Viewed 1744

I have some code in which I need to open files that are sometimes .csv files, but other times .xlsx files. I've imported openpyxl to handle the Excel files.

On switching from Python 3.7 to 3.8, I've found that using the open keyword (which I intend to refer to Python's built-in open function) results in calls to openpyxl's load_workbook() function, which isn't what I want.

Here's a code snippet that demonstrates the issue:

from openpyxl import *
from tkinter import *
import tkinter.filedialog

root = Tk()
root.withdraw()

fileName = tkinter.filedialog.askopenfilename(parent=root, title='Select file.')

with open(fileName, 'w', encoding='utf-8') as file:
    print('fileName')

This code is supposed to:

  • Pop up a dialog box prompting you to select a file
  • Open that file in Python
  • Print its file name

In 3.7, that's exactly what it does; the script runs fine and prints out the file name. However, when I run it in 3.8, I receive the following error message:

Traceback (most recent call last):
  File "C:\Users\[username]\Documents\Python Scripts\test\test.py", line 10, in <module>
    with open(fileName, 'w', encoding='utf-8') as file:
TypeError: load_workbook() got an unexpected keyword argument 'encoding'

The load_workbook() method is mad because I passed it an 'encoding' argument, which it wasn't expecting. If I remove the 'encoding' argument, I instead get the following error:

Traceback (most recent call last):
  File "C:\Users\[username]\Documents\Python Scripts\test\test.py", line 10, in <module>
    with open(fileName, 'w') as file:
  File "C:\Users\[username]\AppData\Local\Programs\Python\Python38-32\lib\site-packages\openpyxl\reader\excel.py", line 312, in load_workbook
    reader = ExcelReader(filename, read_only, keep_vba,
  File "C:\Users\[username]\AppData\Local\Programs\Python\Python38-32\lib\site-packages\openpyxl\reader\excel.py", line 124, in __init__
    self.archive = _validate_archive(fn)
  File "C:\Users\[username]\AppData\Local\Programs\Python\Python38-32\lib\site-packages\openpyxl\reader\excel.py", line 94, in _validate_archive
    raise InvalidFileException(msg)
openpyxl.utils.exceptions.InvalidFileException: openpyxl does not support .csv file format, please check you can open it with Excel first. Supported formats are: .xlsx,.xlsm,.xltx,.xltm

Now it's mad because I'm trying to open a .csv file, and openpyxl can only open Excel files. But I don't understand why openpyxl is even involved here - all I've done is import the module at the top! The open keyword is supposed to be calling Python's built-in function, not a method from openpyxl.


Questions:

  • Why is load_workbook() getting called under these circumstances in 3.8 (but not in 3.7)?
  • How can I convince Python to use its built-in open function instead?
3 Answers

I had the same problem and fixed it by restricting my import. Since I was only using the load_workbook function, I replaced from openpyxl import * with from openpyxl import load_workbook.

Use io.open. You have to import io at the top of the script.

openpyxl.open is an alias for openpyxl.load_workbook, added in version 3.0. You've imported that alias with from openpyxl import *. (Your Python 3.7 setup was probably using an old openpyxl version.)

Stop using import *! This is a textbook example of what goes wrong when you use import *. Use import openpyxl and access the contents explicitly with openpyxl.whatever.

Related