Почему функция Pandas read_excel возвращает ошибку в Pyinstaller .exe, но не в интерпретаторе Python? - PullRequest
0 голосов
/ 06 сентября 2018

Я использую функцию Pandas read_excel для импорта данных из электронной таблицы. Это прекрасно работает при запуске под интерпретатором Python, но когда я собираю exe с помощью PyInstaller, он возвращает IndexError.

Вот упрощенный код pandas_test.py, который демонстрирует проблему:

import pandas as pd

filepath = 'C:/Users/User/Documents/Development/Python/PHL/Test Data/Study 
template mock-up.xlsx'
df = pd.read_excel(filepath, sheet_name='Data Entry', index_col=9)
print(df.head())

Это прекрасно работает под Python 3.6 с пандами 0.23.4 и xlrd 1.1.0.

Когда я собираю pandas_test.py с PyInstaller, он успешно выдает pandas_test.exe, но я получаю эту ошибку:

Traceback (most recent call last):
  File "pandas_test.py", line 4, in <module>
  File "site-packages\pandas\io\excel.py", line 212, in read_excel
  File "site-packages\pandas\io\excel.py", line 513, in _parse_excel
  File "site-packages\pandas\io\parsers.py", line 1912, in TextParser
  File "site-packages\pandas\io\parsers.py", line 764, in __init__
  File "site-packages\pandas\io\parsers.py", line 995, in _make_engine
  File "site-packages\pandas\io\parsers.py", line 2021, in __init__
  File "site-packages\pandas\io\parsers.py", line 2772, in _get_index_name
  File "site-packages\pandas\io\parsers.py", line 3084, in _clean_index_names
IndexError: list index out of range
[17264] Failed to execute script pandas_test

Я прочитал вывод PyInstaller, но ничего явно не связано:

887 INFO: PyInstaller: 3.3.1
887 INFO: Python: 3.6.2
889 INFO: Platform: Windows-10-10.0.17134-SP0
892 INFO: wrote C:\Users\User\Documents\Development\Python\PandaTest\pandas_test.spec

Я мог бы понять, если какой-то модуль не был найден, но почему IndexError только в развернутом коде?

1 Ответ

0 голосов
/ 13 февраля 2019

Я встречал такие же ошибки, как и вы, но в моем случае нет предупреждения, пока я не запустил его, чтобы получить «обнаруженную фатальную ошибку» для сценария ниже (Excelfile.parse эквивалентен read_excel (ExcelFile, ...), просто попробуйте посмотрим, сможет ли Pyinstaller работать с ним или нет)

import xlrd
import pandas as pd
from os.path import join, isfile
from os import environ
if isfile(join(environ['USERPROFILE'],'Downloads','Report_15_13__12_12_2018.xlsx')):
    rd=pd.Excelfile(join(environ['USERPROFILE'],'Downloads','Report_15_13__12_12_2018.xlsx'))
    df1=rd.parse()
    df1.to_excel(join(environ['USERPROFILE'],'Downloads','test.xls'))

Я не могу найти ответ о том, как преодолеть, но копируя код из панд (https://github.com/pandas-dev/pandas/blob/v0.24.1/pandas/io/excel.py#L658-L718), я успешно обошел его. В моем случае у меня есть только 1 лист, но я считаю, что поддержка нескольких листов легко поддерживается .

from xlrd import (xldate, XL_CELL_DATE,
                          XL_CELL_ERROR, XL_CELL_BOOLEAN,
                          XL_CELL_NUMBER,open_workbook)

from datetime import date, datetime, time, timedelta
from pandas import DataFrame
from numpy import array,nan
from os import environ
from os.path import join

book=open_workbook(join(environ['USERPROFILE'],'Downloads','excel_to_read.xls'))
epoch1904 = book.datemode
sheet=book.sheet_by_index(0)
def _parse_cell(cell_contents, cell_typ):
    """converts the contents of the cell into a pandas
        appropriate object"""

    if cell_typ == XL_CELL_DATE:

        # Use the newer xlrd datetime handling.
        try:
            cell_contents = xldate.xldate_as_datetime(
                cell_contents, epoch1904)
        except OverflowError:
            return cell_contents

        # Excel doesn't distinguish between dates and time,
        # so we treat dates on the epoch as times only.
        # Also, Excel supports 1900 and 1904 epochs.
        year = (cell_contents.timetuple())[0:3]
        if ((not epoch1904 and year == (1899, 12, 31)) or
                (epoch1904 and year == (1904, 1, 1))):
            cell_contents = time(cell_contents.hour,
                                    cell_contents.minute,
                                    cell_contents.second,
                                    cell_contents.microsecond)

    elif cell_typ == XL_CELL_ERROR:
        cell_contents = nan
    elif cell_typ == XL_CELL_BOOLEAN:
        cell_contents = bool(cell_contents)
    elif cell_typ == XL_CELL_NUMBER:
        # GH5394 - Excel 'numbers' are always floats
        # it's a minimal perf hit and less surprising
        val = int(cell_contents)
        if val == cell_contents:
            cell_contents = val
    return cell_contents

data = []


for i in range(sheet.nrows):
    row = [_parse_cell(value, typ)
            for value, typ in zip(sheet.row_values(i),
                                    sheet.row_types(i))]
    data.append(row)
NoOfColumns=len(sheet.row_values(i))
NoOfRows=sheet.nrows-1
DataFrame(array(data[1:]).reshape(NoOfRows,NoOfColumns),columns=data[0]).to_excel(join(environ['USERPROFILE'],'Desktop','test.xlsx'),index=False, engine='xlsxwriter')

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...