classification
Title: Locale-dependent exception for float width argument to Tkinter widget constructor
Type: behavior Stage: needs patch
Components: Documentation, Tkinter Versions: Python 3.3, Python 3.4, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: asvetlov Nosy List: asvetlov, gpolo, hans.bering, kbk, r.david.murray, serhiy.storchaka, terry.reedy
Priority: normal Keywords:

Created on 2011-07-14 15:05 by hans.bering, last changed 2014-02-03 17:00 by BreamoreBoy.

Files
File name Uploaded Description Edit
badScreenSizeTk.py hans.bering, 2011-07-14 15:05 locale-dependent crash when calling widget constructor with float width argument
Messages (9)
msg140338 - (view) Author: Hans Bering (hans.bering) Date: 2011-07-14 15:05
The attached script will crash on a current Ubuntu with Python 3.2 + tcl/tk when using a locale which uses a comma as a decimal separator (e.g., German). It will not crash when using a locale which uses a dot as the decimal separator (e.g., English). In case of the crash, the output and stacktrace are as follows:

locale = ('de_DE', 'UTF8')
Traceback (most recent call last):
  File "tkinterCrash.py", line 20, in <module>
    tkcanvas = Canvas(master=master, width=w, height=2, borderwidth=4)
  File "/usr/lib/python3.2/tkinter/__init__.py", line 2101, in __init__
    Widget.__init__(self, master, 'canvas', cnf, kw)
  File "/usr/lib/python3.2/tkinter/__init__.py", line 1961, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: bad screen distance "10.0"

Originally, we stumbled over this problem when using matplotlib, which passes/passed down float types as width arguments on occasions. It has been fixed there since (see https://github.com/matplotlib/matplotlib/pull/387).

The locale dependency can make this problem difficult to debug when it occurs. In our setup, we had a program work on one machine, but it crashed on the next machine, which we believed to have an identical setup; it took us a day to figure out what the difference was. We would expect the constructor to either always work with float arguments, or to always reject them, regardless of locale.

We have been able to reproduce this issue both with Python 2.7.2 and Python 3.2, both under a current Ubuntu and Windows 7.
msg140340 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2011-07-14 15:25
FYI 'crash' is for segfault.  A traceback is "just a bug" :)

I'm not sure that this it is worth having this as a separate bug from #10647, but I'll let someone with tk knowledge decide that.
msg140342 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2011-07-14 16:15
Why is this a bug ? You passed something that is not supposed to work with tk and tk said so.
msg140367 - (view) Author: Hans Bering (hans.bering) Date: 2011-07-14 18:55
Sorry for the misclassification, and thanks for correcting that.

I agree, this issue is most likely related to issue 10647; but at some level I think they must be different, because issue 10647 seems to be specific to Python 3.1 under Windows; I could not reproduce that issue neither under Ubuntu nor with Python 3.2 in Windows. This behaviour on the other hand I could reproduce with Python 2.7 and Python 3.2 in both Ubuntu and Windows. The underlying problem in both cases, I believe, is similar: That int/float arguments are somewhere turned into locale-dependent string representations and later parsed back using a potentially different locale.

Which brings me to why I consider this to be a bug - sorry for not having made that point clearer: The handling of the float argument depends on the system locale. If you change the example script to run with an English locale, you do not get an error; instead, the float is implicitly used as an int, and everything is fine. Only if you use German or a similar locale, will the float trigger an error. So the behaviour is at the very least inconsistent. If treating a float argument as an error is deemed acceptable, then this error should not be locale-dependent.
msg185927 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2013-04-03 14:52
FWIW this can be reproduced on Windows Vista with Python 3.3.1rc1.
msg197766 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-09-15 12:41
This is a bug in Tk. It uses locale-agnostic Tcl_GetDoubleFromObj() in most places, but in some places (especially in canvas) it uses locale-dependent strtod(). And that is even worse, strtod() is used even for parsing comma-delimited floats (@-indices).

We can't fix it from Python side (except perhaps switching to C locale for every Tcl/Tk operation). But in desires a warning in the documentation.
msg197840 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-09-15 22:42
Perhaps we can fix it on the Python side. When self.tk is called with a configuration cnf, cnf is often (always?) first passed to Misc._options, as in BaseWidget.__init__:
        self.tk.call(
            (widgetName, self._w) + extra + self._options(cnf))

Misc._options loops through cnf.items looking for values to and modify (currently callables, tuples, and lists) before passing the result on to tk.call.

We could make a list *countkeys* of cnf (configuration) count items fed to strtod. Then, with that loop, if the locale uses comma decimal separators (or always) convert float values for those keys to ints.

  if comma and k in countkeys: v = int(v)  # or
  if comma and k in countkeyw and isinstance(v, float): v = int(v)

I am presuming that tk truncates fractional parts as int() does; if not, use round().

I cannot verify the bug on US Win7 3.3.2 because 'de_DE.utf8' is an 'unsupported locale' for me. For the C locale, I verified that tk silently accept not only non-integral widths, but also negative widths.
msg197873 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-09-16 07:02
> I am presuming that tk truncates fractional parts as int() does; if not, use round().

Tk uses both truncated and rounded value.

$ rlwrap wish
% canvas .c
.c
% .c configure -width 10.1
% .c configure -width
-width width Width 10c 10
% .c configure -width 10.9
% .c configure -width
-width width Width 10c 11

As you can see 10.9 gives both 10c and 11.
msg197876 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-09-16 07:27
Oh, sorry, 10c is unrelated. Tk uses rounding. I don't know if it requires somewhere actual non-integer values.
History
Date User Action Args
2014-02-03 17:00:46BreamoreBoysetnosy: - BreamoreBoy
2013-09-16 07:27:35serhiy.storchakasetmessages: + msg197876
2013-09-16 07:02:03serhiy.storchakasetmessages: + msg197873
2013-09-15 22:42:00terry.reedysetmessages: + msg197840
2013-09-15 12:41:29serhiy.storchakasetstage: needs patch
messages: + msg197766
components: + Documentation
versions: + Python 3.3, Python 3.4, - Python 3.2
2013-09-15 11:37:43serhiy.storchakasetnosy: + serhiy.storchaka
2013-04-03 14:52:36BreamoreBoysetnosy: + BreamoreBoy
messages: + msg185927
2012-03-14 21:54:54asvetlovsetassignee: asvetlov

nosy: + asvetlov
2011-07-15 20:57:11terry.reedysettitle: Locale-dependent crash for float width argument to Tkinter widget constructor -> Locale-dependent exception for float width argument to Tkinter widget constructor
2011-07-14 18:55:23hans.beringsetmessages: + msg140367
2011-07-14 16:15:43gpolosetmessages: + msg140342
2011-07-14 15:26:32r.david.murraysetsuperseder: scrollbar crash in non-US locale format settings ->
2011-07-14 15:26:20r.david.murraysetnosy: + gpolo
2011-07-14 15:25:16r.david.murraysetnosy: + r.david.murray, kbk, terry.reedy
messages: + msg140340

superseder: scrollbar crash in non-US locale format settings
type: crash -> behavior
2011-07-14 15:05:06hans.beringcreate