1

I’m working on a Tkinter application where the user can input a few fields before clicking on a button which is supposed to write what he wrote in a TreeView widget. This worked well when running on my mac, but on Windows, when calling insert() on the TreeView, I get a "builtins.UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 2570: invalid continuation byte".

I tried to call encode("utf-8") on the strings passed in the insert method, but this does not work.

for i in range(0, len(self.commandList)):
            resumeTree.insert("", i, "", values = (self.commandList[i][0].encode("utf-8"), self.commandList[i][1].encode("utf-8"), self.commandList[i][2].encode("utf-8")), text = i)

My inputs may contain special caracter but the error is the same when I tried :

for i in range(0, len(self.commandList)):
            resumeTree.insert("", i, "", values = ("a", "b", "c"), text = i)

Here is how my widget is defined :

resumeTree = ttk.Treeview(resumeFrame)
        resumeTree['show'] = 'headings'
        resumeTree["columns"]=("type","poids", "prix")
        resumeTree.column("type", minwidth = 15, width = 200)
        resumeTree.column("poids", minwidth = 75, width = 50)
        resumeTree.column("prix", minwidth = 75, width = 50)
        resumeTree.heading("type", text = "Type", anchor = tk.W)
        resumeTree.heading("poids", text = "Poids (g)", anchor = tk.W)
        resumeTree.heading("prix", text = "Prix total (euro)", anchor = tk.W)
        resumeTree.Scrollable = True

Here is the backtrace of the error

File "C:\Users\Camille\Documents\GestionVentesClassique\main.py", line 165, in <module>
File "C:\Users\Camille\Documents\GestionVentesClassique\main.py", line 162, in main
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\tkinter\__init__.py", line 1283, in mainloop
  self.tk.mainloop(n)
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\tkinter\__init__.py", line 1709, in __call__
  self.widget._report_exception()
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\tkinter\__init__.py", line 1452, in _report_exception
  root.report_callback_exception(exc, val, tb)
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\tkinter\__init__.py", line 2098, in report_callback_exception
  traceback.print_exception(exc, val, tb)
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\traceback.py", line 104, in print_exception
  type(value), value, tb, limit=limit).format(chain=chain):
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\traceback.py", line 508, in __init__
  capture_locals=capture_locals)
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\traceback.py", line 363, in extract
  f.line
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\traceback.py", line 285, in line
  self._line = linecache.getline(self.filename, self.lineno).strip()
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\linecache.py", line 16, in getline
  lines = getlines(filename, module_globals)
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\linecache.py", line 47, in getlines
  return updatecache(filename, module_globals)
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\linecache.py", line 137, in updatecache
  lines = fp.readlines()
File "C:\Users\Camille\AppData\Local\Programs\Python\Python37-32\Lib\codecs.py", line 322, in decode
  (result, consumed) = self._buffer_decode(data, self.errors, final)

builtins.UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 2582: invalid continuation byte
LeoQLF
  • 63
  • 1
  • 2
  • 6
  • Have you tried `encoding = "ISO-8859-1"` as suggested in [this post](https://stackoverflow.com/questions/19699367/unicodedecodeerror-utf-8-codec-cant-decode-byte)? – Henry Yik Aug 08 '19 at 14:21
  • I just tried .encode("ISO-8859-1"), but the result is the same. – LeoQLF Aug 08 '19 at 14:29
  • @HenryYik where would you add this `encoding` parameter? There's no `open` or `read_csv` call in the OP's code. – lenz Aug 08 '19 at 19:58
  • Leo, can you show the traceback? A value like `("a", "b", "c")` can't produce a UnicodeDecodeError (it's already decoded), so the problem probably lies somewhere else. Btw: Python 2 or Python 3? – lenz Aug 08 '19 at 20:00
  • You're right, I should have put the backtrace in, I just edited my post. It's python 3, any idea where this could come from ? – LeoQLF Aug 09 '19 at 15:08

1 Answers1

0

Python 3 handle strings as text - and tkinter will deliver you decoded text strings and take in decoded text strings, no matter what characters are in then, and you should never have to worry about encoding/decoding between tkinter widgets.

So, any attempt to encode or decode strings before passing then to any tkinter calls or settings is wrong to start - just leave the text alone.

That said, I created such a widget, and could indeed pump accented characters to it. However, I do get errors if I send a fixed third ordered argument ("iid") as you are putting there - resumeTree.insert("", i, "", ...) - this second empty string ("") will trigger a TclError exception (not UnicodeDecode) - the docs say this valus is optional, but that it should be unique for the widget

If I just do not pass it at all, the widget builds fine.

What is taking place is probably a bug in tkitner itself when trying to display the original error message in Windows (I am on Linux). Leave the "iid" parameter out of your call (or use a unique value for it) and it should work:

...
    resumeTree.insert("", i, values=tuple(self.commandList[i]), text= )

And, of course, remove any attempts do "decode" or "encode" your text values - you should just add an "encoding" parameter if you are outputting your data to a text file, then you use it when calling open(...). If your data is being saved to a database, rendered to html, or whatever you should not have to worry about that - the libraries will pick the best default encoding.

jsbueno
  • 99,910
  • 10
  • 151
  • 209