Repository: ipython/ipython

Issue:
Possible crash reporting 'French' OS error message
Hi, FYI possible crash with this error:
`UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 39: ordinal not in range(128)`

**Context**: I am running and external program through ipython; my external program crashed for some reason. As normal ipython caught this error, but while trying to report it, ipython crashed as well. It seems to be due to the tentative to create a string (str) from a unicode one, ie including 'French' accents as reported by windows (see the string s below). 

I am runing python2.7, ipython 4.2, windows7.

Thanks

```
File "C:\Program Files (x86)\python27\lib\site-packages\IPython\core\interactiveshell.py", line 2902, in run_code
    self.showtraceback()

  File "C:\Program Files (x86)\python27\lib\site-packages\IPython\core\interactiveshell.py", line 1830, in showtraceback
    value, tb, tb_offset=tb_offset)

  File "C:\Program Files (x86)\python27\lib\site-packages\IPython\core\ultratb.py", line 1392, in structured_traceback
    self.tb = tb

  File "C:\Program Files (x86)\python27\lib\site-packages\IPython\core\ultratb.py", line 1309, in structured_traceback
    elist = self._extract_tb(tb)

  File "C:\Program Files (x86)\python27\lib\site-packages\IPython\core\ultratb.py", line 640, in structured_traceback
    # The exception info should be a single entry in the list.

  File "C:\Program Files (x86)\python27\lib\site-packages\IPython\core\ultratb.py", line 752, in _format_exception_only
    list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 39: ordinal not in range(128)

In [166]: %debug
> c:\program files (x86)\python27\lib\site-packages\ipython\core\ultratb.py(752)_format_exception_only()
    750                 s = self._some_str(value)
    751             if s:
--> 752                 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
    753                                               Colors.Normal, s))
    754             else:

ipdb> stype
 '\x1b[1;31mWindowsError\x1b[0m'

ipdb> Colors
{'em': '\x1b[1;36m', 'filenameEm': '\x1b[1;32m', 'excName': '\x1b[1;31m', 'valEm': '\x1b[1;34m', 'nameEm': '\x1b[1;35m', 'line': '\x1b[1;33m', 'topline': '\x1b[1;31m', 'name': '\x1b[0;35m', 'caret': '\x1b[1;37m', 'val': '\x1b[0;32m', 'vName': '\x1b[0;36m', 'Normal': '\x1b[0m', 'filename': '\x1b[0;32m', 'linenoEm': '\x1b[1;32m', 'lineno': '\x1b[0;32m', 'normalEm': '\x1b[1;36m'}

ipdb> print s
[Error 32] Le processus ne peut pas acc�der au fichier car ce fichier est utilis� par un autre processus
```



Discussion:
Can you install IPython 4.1 and see if you still have this problem? I suspect this is a regression in 4.2.

Also, if you use non-ascii text on Windows with any regularity, especially files, I would **strongly** recommend upgrading to Python 3 as soon as possible. Python 2 will never run out of problems with unicode, especially on Windows.

Installing latest IPython before 4.2:

```
pip install 'ipython<4.2'
```

What are `type(stype)` and `type(s)`?

And what is the line of code you are running when this happens?

Both are str

s is '[Error 32] Le processus ne peut pas acc\xe9der au fichier car ce fichier est utilis\xe9 par un autre processus' (meaning; 'the process cannot access a file, because this file is already used by another process'; I do understand my crash, it is normal for me)
Therefore the \xe9 char, seems unicode and is outside range(128).
You are right, I should move to python 3, but I will miss some packages.
Meanwhile this error/exception could be caught here to avoid the crash.

BTW, it does crash with 4.1.2

The line is 
`os.spawnl(os.P_WAIT,'myprocess.exe','myprocess.exe myoptions')`
it is run within spyder.

Thanks

> You are right, I should move to python 3, but I will miss some packages.

What packages would you be missing? There are fewer and fewer I know of that don't support Python 3.


Resolving patch:
diff --git a/IPython/core/ultratb.py b/IPython/core/ultratb.py
--- a/IPython/core/ultratb.py
+++ b/IPython/core/ultratb.py
@@ -709,10 +709,10 @@ def _format_exception_only(self, etype, value):
         have_filedata = False
         Colors = self.Colors
         list = []
-        stype = Colors.excName + etype.__name__ + Colors.Normal
+        stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
         if value is None:
             # Not sure if this can still happen in Python 2.6 and above
-            list.append(py3compat.cast_unicode(stype) + '\n')
+            list.append(stype + '\n')
         else:
             if issubclass(etype, SyntaxError):
                 have_filedata = True
@@ -752,10 +752,10 @@ def _format_exception_only(self, etype, value):
             except Exception:
                 s = self._some_str(value)
             if s:
-                list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
+                list.append('%s%s:%s %s\n' % (stype, Colors.excName,
                                               Colors.Normal, s))
             else:
-                list.append('%s\n' % str(stype))
+                list.append('%s\n' % stype)
 
         # sync with user hooks
         if have_filedata:
@@ -793,9 +793,9 @@ def show_exception_only(self, etype, evalue):
     def _some_str(self, value):
         # Lifted from traceback.py
         try:
-            return str(value)
+            return py3compat.cast_unicode(str(value))
         except:
-            return '<unprintable %s object>' % type(value).__name__
+            return u'<unprintable %s object>' % type(value).__name__
 
 
 #----------------------------------------------------------------------------


Test patch:
diff --git a/IPython/core/tests/test_ultratb.py b/IPython/core/tests/test_ultratb.py
--- a/IPython/core/tests/test_ultratb.py
+++ b/IPython/core/tests/test_ultratb.py
@@ -99,6 +99,21 @@ def test_iso8859_5(self):
             with tt.AssertPrints("ZeroDivisionError"):
                 with tt.AssertPrints(u'дбИЖ', suppress=False):
                     ip.run_cell('fail()')
+    
+    def test_nonascii_msg(self):
+        cell = u"raise Exception('é')"
+        expected = u"Exception('é')"
+        ip.run_cell("%xmode plain")
+        with tt.AssertPrints(expected):
+            ip.run_cell(cell)
+
+        ip.run_cell("%xmode verbose")
+        with tt.AssertPrints(expected):
+            ip.run_cell(cell)
+
+        ip.run_cell("%xmode context")
+        with tt.AssertPrints(expected):
+            ip.run_cell(cell)
 
 
 class NestedGenExprTestCase(unittest.TestCase):