1. 程式人生 > 實用技巧 >xlrd》操作excel 出現的問題:File "D:\python37\lib\site-packages\xlrd\formula.py", line 1150, in evaluate_name_formula assert len(tgtobj.stack) == 1

xlrd》操作excel 出現的問題:File "D:\python37\lib\site-packages\xlrd\formula.py", line 1150, in evaluate_name_formula assert len(tgtobj.stack) == 1

xlrd》操作excel 出現的問題

報錯如下:

D:\python37\python.exe D:/testWang/waimai/tools/get_excelData.py
*** formula/tFunc unknown FuncID:186
*** formula/tFunc unknown FuncID:186
*** formula/tFunc unknown FuncID:186
*** formula/tFunc unknown FuncID:186
*** formula/tFunc unknown FuncID:186
*** formula/tFunc unknown FuncID:186
Traceback (most recent call last):
File "D:/testWang/waimai/tools/get_excelData.py", line 42, in <module>
print(get_excelData('登入模組', 2, 7))
File "D:/testWang/waimai/tools/get_excelData.py", line 18, in get_excelData
workBook = xlrd.open_workbook(excelDir, formatting_info=True)
File "D:\python37\lib\site-packages\xlrd\__init__.py", line 157, in open_workbook
ragged_rows=ragged_rows,
File "D:\python37\lib\site-packages\xlrd\book.py", line 117, in open_workbook_xls
bk.parse_globals()
File "D:\python37\lib\site-packages\xlrd\book.py", line 1245, in parse_globals
self.names_epilogue()
File "D:\python37\lib\site-packages\xlrd\book.py", line 1043, in names_epilogue
evaluate_name_formula(self, nobj, namex, blah=blah)
File "D:\python37\lib\site-packages\xlrd\formula.py", line 1150, in evaluate_name_formula
assert len(tgtobj.stack) == 1
AssertionError

Process finished with exit code 1


問題現象:

python指令碼在呼叫xlrd模組解析excel檔案時,提示如下錯誤:

*** formula/tFunc unknown FuncID:186

進而導致整個指令碼崩潰。

原因分析:

xlrd模組在解析excel檔案時會嘗試解析excel中的函式,這些函式被定義在一個字典

而當前xlrd對excel函式的支援並不全,比如index:186的就不支援;

遇到這種不支援的函式,xlrd會assert異常,終止解析;

其實這種做法無可厚非,遇到未知的情況,在不能保證正確的情況下終止解析,看起來是最好的;

但是,在有些情況下,我們還是希望能夠選擇忽略掉這個錯誤接著解析的,但是xlrd沒有給我們這個選擇。

解決方案:

思路:忽略異常,繼續解析檔案;

思路一: 讓assert無效。

我知道c++在release版中assert都是無效的,但是python中貌似做不到。

我嘗試過把指令碼編譯成pyc後執行,但仍會assert的。

思路二: 修改xlrd

既然問題出在xlrd上,那麼最直接的辦法就是修改xlrd;這裡有兩種方案:

一、方案一:

參考網上的方法,對未知的excel函式,假裝知道——在xlrd的字典中,新增FuncID:186,讓xlrd認為支援這個函式,不再報錯:

/usr/local/lib/python3.4/site-packages/xlrd-1.0.0-py3.4.egg/xlrd/formula.py:240

  1. 184: ('FACT', 1, 1, 0x02, 1, 'V', 'V'),
  2. + 186: ('HACKED', 1, 1, 0x02, 1, 'V', 'V'),
  3. 189: ('DPRODUCT', 3, 3, 0x02, 3, 'V', 'RRR'),

二、方案二:

與方案一思路一致,刪除assert,讓程式繼續進行下去;

/usr/local/lib/python3.4/site-packages/xlrd-1.0.0-py3.4.egg/xlrd/formula.py:1307

  1. else:
  2. # assert len(tgtobj.stack) == 1
  3. res = copy.deepcopy(tgtobj.stack[0])

優劣:

方案一:修改後影響未知,xlrd最終會怎麼處理186這個id我並不清楚;

方案二:相對安全,但我們喪失了提前得知指令碼有問題的優勢;

思路三: 使用期他的excel庫解析;

逃避方案:xlwings, openpyxl, pandas, win32com, xlsxwriter, DataNitro

結論

綜合考慮,目前我採用的是第二個思路的方案二。

參考資料:

https://stackoverflow.com/questions/29971186/python-xlrd-error-formula-tfunc-unknown-funcid186

https://github.com/python-excel/xlrd/issues/154