There is not much difference except the syntax. Technically, ExcelFile is a class, and read_excel is a function. In any case, the actual analysis is processed by the _parse_excel method defined in ExcelFile .
In earlier versions of pandas read_excel consisted entirely of one statement (except for comments):
return ExcelFile(path_or_buf,kind=kind).parse(sheetname=sheetname, kind=kind, **kwds)
And ExcelFile.parse did not do much more than calling ExcelFile._parse_excel .
In recent versions of pandas, read_excel ensures that it has an ExcelFile object (and creates it if it is not), and then directly _parse_excel method:
if not isinstance(io, ExcelFile): io = ExcelFile(io, engine=engine) return io._parse_excel(...)
and with updated (and unified) parameter handling, ExcelFile.parse indeed the only statement:
return self._parse_excel(...)
This is why the docs for ExcelFile.parse now say
Equivalent to read_excel (ExcelFile, ...). See the read_excel documentation line for more information on accepted parameters.
As for the other answer, which claims that ExcelFile.parse faster in a loop, it really comes down to whether you create an ExcelFile object from scratch every time. Of course, you can create your ExcelFile once outside the loop and pass it to read_excel inside the loop:
xl = pd.ExcelFile(path) for name in xl.sheet_names: df = pd.read_excel(xl, name)
That would be equivalent
xl = pd.ExcelFile(path) for name in xl.sheet_names: df = xl.parse(name)
If your cycle includes different paths (in other words, you read many different books, and not just several sheets in one book), then you still can not do without creating a new instance of ExcelFile for each path, and then again, and ExcelFile.parse and read_excel will be equivalent (and equally slow).