Ich habe xlrd, pandas, openpyxl und andere solche Bibliotheken ausprobiert und alle scheinen exponentielle Zeit in Anspruch zu nehmen, wenn die Dateigröße zunimmt, während die gesamte Datei gelesen wird. Die anderen oben genannten Lösungen, bei denen 'on_demand' verwendet wurde, funktionierten bei mir nicht. Wenn Sie zunächst nur die Blattnamen abrufen möchten, funktioniert die folgende Funktion für XLSX-Dateien.
def get_sheet_details(file_path):
sheets = []
file_name = os.path.splitext(os.path.split(file_path)[-1])[0]
# Make a temporary directory with the file name
directory_to_extract_to = os.path.join(settings.MEDIA_ROOT, file_name)
os.mkdir(directory_to_extract_to)
# Extract the xlsx file as it is just a zip file
zip_ref = zipfile.ZipFile(file_path, 'r')
zip_ref.extractall(directory_to_extract_to)
zip_ref.close()
# Open the workbook.xml which is very light and only has meta data, get sheets from it
path_to_workbook = os.path.join(directory_to_extract_to, 'xl', 'workbook.xml')
with open(path_to_workbook, 'r') as f:
xml = f.read()
dictionary = xmltodict.parse(xml)
for sheet in dictionary['workbook']['sheets']['sheet']:
sheet_details = {
'id': sheet['@sheetId'],
'name': sheet['@name']
}
sheets.append(sheet_details)
# Delete the extracted files directory
shutil.rmtree(directory_to_extract_to)
return sheets
Da es sich bei allen xlsx im Grunde genommen um komprimierte Dateien handelt, extrahieren wir die zugrunde liegenden XML-Daten und lesen die Blattnamen direkt aus der Arbeitsmappe, was im Vergleich zu den Bibliotheksfunktionen einen Bruchteil einer Sekunde dauert.
Benchmarking: (Auf einer 6-MB-xlsx-Datei mit 4 Blättern)
Pandas, xlrd: 12 Sekunden
openpyxl: 24 Sekunden
Vorgeschlagene Methode: 0,4 Sekunden
Da ich nur die Blattnamen lesen musste, nervte mich der unnötige Aufwand beim Lesen der gesamten Zeit, sodass ich stattdessen diesen Weg einschlug.
ExcelFile
? Angenommen, ich schaue in der Liste der Blätter nach und entscheide mich, N davon zu laden. Soll ich an diesem Punktread_excel
(die neue Schnittstelle) für jedes Blatt aufrufen oder mich daran haltenx1.parse
?