385

I am using Python-2.6 CGI scripts but found this error in server log while doing json.dumps(),

Traceback (most recent call last):
  File "/etc/mongodb/server/cgi-bin/getstats.py", line 135, in <module>
    print json.dumps(​​__get​data())
  File "/usr/lib/python2.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xa5 in position 0: invalid start byte

​Here ,

​__get​data() function returns dictionary {} .

Before posting this question I have referred this of question os SO.


UPDATES

Following line is hurting JSON encoder,

now = datetime.datetime.now()
now = datetime.datetime.strftime(now, '%Y-%m-%dT%H:%M:%S.%fZ')
print json.dumps({'current_time': now}) # this is the culprit

I got a temporary fix for it

print json.dumps( {'old_time': now.encode('ISO-8859-1').strip() })

But I am not sure is it correct way to do it.

MattDMo
  • 100,794
  • 21
  • 241
  • 231
Deepak Ingole
  • 14,912
  • 10
  • 47
  • 79
  • 1
    It looks like you have some string data in the dictionary that can't be encoded/decoded. What's in the `dict`? – mgilson Mar 06 '14 at 05:53
  • @mgilson yup master I understood the issue but donno how to deal with it..`dict` has `list, dict, python timestamp value ` – Deepak Ingole Mar 06 '14 at 05:53
  • to debug , put lines that throws error . It will be more useful . – Priyank Patel Mar 06 '14 at 05:55
  • 1
    @Pilot -- Not really. The real problem is buried somewhere in `__getdata`. I don't know *why* you're getting a non-decodable character. You can try to come up with patches on the dict to make it work, but those are mostly just asking for more problems later. I would try printing the dict to see where the non-ascii character is. Then figure out how that field got calculated/set and work backward from there. – mgilson Mar 06 '14 at 07:04
  • Master @mgilson can you please check updated question – Deepak Ingole Mar 06 '14 at 12:06
  • 2
    Possible duplicate of [UnicodeDecodeError: 'utf8' codec can't decode byte 0x9c](http://stackoverflow.com/q/12468179/1677912). – Mogsdad Mar 05 '16 at 18:27
  • 1
    I had that same error when trying to read a .csv file which had some non-ascii characters in it. Removing those characters (as suggested below) solved the issue. – Dmitriy R. Starson Feb 14 '17 at 03:27
  • **But I am not sure is it correct way to do it.** It is indeed... – Romeo Sierra Oct 18 '20 at 08:19

21 Answers21

378

If you get this error when trying to read a csv file, the read_csv() function from pandas lets you set the encoding:

import pandas as pd
data = pd.read_csv(filename, encoding='unicode_escape')
endive1783
  • 827
  • 1
  • 8
  • 18
MSalty
  • 4,086
  • 2
  • 12
  • 16
  • 14
    Only if you using `pandas` – Valeriy Dec 30 '19 at 15:46
  • 6
    sorry, this didn't working, I again had the same error. but when I used ('filename.csv', engine ='python'). This worked. – basavaraj_S Jan 28 '20 at 10:29
  • works for pysrt too, pysrt.open(subfilename, encoding='unicode_escape') and I think this solution should work with Un-encoded text / plain text for any library that supports encoding on file open "unicode_escape" will open file , but if you have non-ascii you should give specific encoding for example for Turkish encoding='ISO-8859-9' – Gorkem Mar 08 '21 at 11:09
  • I had the same problem using pandas and this solution worked. However, is there a way to change the file itself? My csv file was generated by Excel and I don't see any special characters. So I am thinking there must be a way to re-save this file so that I don't have to use 'unicode-escape'. – spark Jan 10 '23 at 15:39
  • Also worked inside R with reticulate. – Geo Vogler Jan 12 '23 at 19:04
174

By default open function has io attribute 'r' as in read only. This can be set to 'rb' as in read binary.

Try the below code snippet:

with open(path, 'rb') as f:
  text = f.read()
endive1783
  • 827
  • 1
  • 8
  • 18
Soumyaansh
  • 8,626
  • 7
  • 45
  • 45
118

The error is because there is some non-ascii character in the dictionary and it can't be encoded/decoded. One simple way to avoid this error is to encode such strings with encode() function as follows (if a is the string with non-ascii character):

a.encode('utf-8').strip()
Jean-Francois T.
  • 11,549
  • 7
  • 68
  • 107
Santosh Ghimire
  • 3,087
  • 8
  • 35
  • 63
  • 2
    Since UTF-8 is back-compatible with the oldschool 7-bit ASCII you should just encode everything. For characters in the 7-bit ASCII range this encoding will be an identity mapping. – Tadeusz A. Kadłubowski Mar 06 '14 at 07:47
  • 81
    This doesn't seem real clear. When importing a csv file how do you use this code? – Dave Sep 17 '19 at 15:13
  • 1
    The same issue appears for me when executing an sqlalchemy query, how would I encode the query (has no .encode, since its not a string)? – c8999c 3f964f64 Jul 03 '20 at 09:27
51

Your string has a non ascii character encoded in it.

Not being able to decode with utf-8 may happen if you've needed to use other encodings in your code. For example:

>>> 'my weird character \x96'.decode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x96 in position 19: invalid start byte

In this case, the encoding is windows-1252 so you have to do:

>>> 'my weird character \x96'.decode('windows-1252')
u'my weird character \u2013'

Now that you have Unicode, you can safely encode into utf-8.

shiva
  • 5,083
  • 5
  • 23
  • 42
JCF
  • 651
  • 5
  • 9
  • 5
    I have created a simple page which may help establish the encoding of some unexpected "mystery bytes"; https://tripleee.github.io/8bit/ – tripleee Feb 04 '20 at 18:50
  • This solved it for my case with pd.read(), just switching to encoding='windows-1252' instead of encoding='utf-8' – gseattle Jan 05 '23 at 10:49
39

On read csv, I added an encoding method:

import pandas as pd
dataset = pd.read_csv('sample_data.csv', header= 0,
                        encoding= 'unicode_escape')
shiva
  • 5,083
  • 5
  • 23
  • 42
37

This solution worked for me:

import pandas as pd
data = pd.read_csv("training.csv", encoding = 'unicode_escape')
shiva
  • 5,083
  • 5
  • 23
  • 42
26

Inspired by @aaronpenne and @Soumyaansh

f = open("file.txt", "rb")
text = f.read().decode(errors='replace')
shiva
  • 5,083
  • 5
  • 23
  • 42
Punnerud
  • 7,195
  • 2
  • 54
  • 44
  • I got "AttributeError: 'str' object has no attribute 'decode'". Not sure what went wrong? – Victor Wong Dec 06 '18 at 03:14
  • 2
    Did you include b to the "rb"? The b is for opening the file as byte-formated. If you just use r it is string, and don't include decode. – Punnerud Dec 06 '18 at 11:11
17

Set default encoder at the top of your code

import sys
reload(sys)
sys.setdefaultencoding("ISO-8859-1")
HimalayanCoder
  • 9,630
  • 6
  • 59
  • 60
17

Simple Solution:

import pandas as pd
df = pd.read_csv('file_name.csv', engine='python')
Gil Baggio
  • 13,019
  • 3
  • 48
  • 37
16

As of 2018-05 this is handled directly with decode, at least for Python 3.

I'm using the below snippet for invalid start byte and invalid continuation byte type errors. Adding errors='ignore' fixed it for me.

with open(out_file, 'rb') as f:
    for line in f:
        print(line.decode(errors='ignore'))
shiva
  • 5,083
  • 5
  • 23
  • 42
aaronpenne
  • 580
  • 5
  • 10
  • 6
    Of course, this silently discards information. A much better fix is to figure out what's supposed to be there, and fixing the original problem. – tripleee Feb 04 '20 at 18:47
14

If the above methods are not working for you, you may want to look into changing the encoding of the csv file itself.

Using Excel:

  1. Open csv file using Excel
  2. Navigate to File menu option and click Save As
  3. Click Browse to select a location to save the file
  4. Enter intended filename
  5. Select CSV (Comma delimited) (*.csv) option
  6. Click Tools drop-down box and click Web Options
  7. Under Encoding tab, select the option Unicode (UTF-8) from Save this document as drop-down list
  8. Save the file

Using Notepad:

  1. Open csv file using notepad
  2. Navigate to File > Save As option
  3. Next, select the location to the file
  4. Select the Save as type option as All Files(.)
  5. Specify the file name with .csv extension
  6. From Encoding drop-down list, select UTF-8 option.
  7. Click Save to save the file

By doing this, you should be able to import csv files without encountering the UnicodeCodeError.

shiva
  • 5,083
  • 5
  • 23
  • 42
Zuo
  • 141
  • 1
  • 2
10

The following snippet worked for me.

import pandas as pd
df = pd.read_csv(filename, sep = ';', encoding = 'latin1', error_bad_lines=False) #error_bad_lines is avoid single line error
amit haldar
  • 129
  • 1
  • 10
  • 1
    error_bad_lines has been deprecated, use on_bad_lines instead, like = on_bad_lines = 'skip' https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html Need to add: this does not help for me – n.r. Apr 05 '23 at 14:27
7

Following line is hurting JSON encoder,

now = datetime.datetime.now()
now = datetime.datetime.strftime(now, '%Y-%m-%dT%H:%M:%S.%fZ')
print json.dumps({'current_time': now}) // this is the culprit

I got a temporary fix for it

print json.dumps( {'old_time': now.encode('ISO-8859-1').strip() })

Marking this as correct as a temporary fix (Not sure so).

Deepak Ingole
  • 14,912
  • 10
  • 47
  • 79
4

You may use any standard encoding of your specific usage and input.

utf-8 is the default.

iso8859-1 is also popular for Western Europe.

e.g: bytes_obj.decode('iso8859-1')

see: docs

shiva
  • 5,083
  • 5
  • 23
  • 42
NoamG
  • 1,145
  • 10
  • 17
  • 2
    Blindly guessing the encoding is likely to produce more errors. Selecting iso8859-1 or cp1251 etc without actually knowing which encoding the file uses will remove the symptom, but produce garbage if you guessed wrong. If it's just a few bytes, it could take years before you notice and fix the *real* error. – tripleee Feb 04 '20 at 18:53
2

After trying all the aforementioned workarounds, if it still throws the same error, you can try exporting the file as CSV (a second time if you already have). Especially if you're using scikit learn, it is best to import the dataset as a CSV file.

I spent hours together, whereas the solution was this simple. Export the file as a CSV to the directory where Anaconda or your classifier tools are installed and try.

shiva
  • 5,083
  • 5
  • 23
  • 42
Sushmita
  • 21
  • 1
1

Instead of looking for ways to decode a5 (Yen ¥) or 96 (en-dash ), tell MySQL that your client is encoded "latin1", but you want "utf8" in the database.

See details in Trouble with UTF-8 characters; what I see is not what I stored

Rick James
  • 135,179
  • 13
  • 127
  • 222
1

I encountered the same error while trying to import to a pandas dataframe from an excel sheet on sharepoint. My solution was using engine='openpyxl'. I'm also using requests_negotiate_sspi to avoid storing passwords in plain text.

import requests
from io import BytesIO
from requests_negotiate_sspi import HttpNegotiateAuth
cert = r'c:\path_to\saved_certificate.cer'
target_file_url = r'https://share.companydomain.com/sites/Sitename/folder/excel_file.xlsx'
response = requests.get(target_file_url, auth=HttpNegotiateAuth(), verify=cert)
df = pd.read_excel(BytesIO(response.content), engine='openpyxl', sheet_name='Sheet1')
Paul
  • 21
  • 1
  • 5
1

Simple solution:

import pandas as pd

df = pd.read_csv('file_name.csv', engine='python-fwf')

If it's not working try to change the engine to 'python' or 'c'.

Timus
  • 10,974
  • 5
  • 14
  • 28
0

In my case, i had to save the file as UTF8 with BOM not just as UTF8 utf8 then this error was gone.

shiva
  • 5,083
  • 5
  • 23
  • 42
luky
  • 2,263
  • 3
  • 22
  • 40
0
from io import BytesIO

df = pd.read_excel(BytesIO(bytes_content), engine='openpyxl')

worked for me

0

I know this doesn't fit directly to the question, but I repeatedly get directed to this when I google the error message.

I did get the error when I mistakenly tried to install a Python package like I would install requirements from a file, i.e., with -r:

# wrong: leads to the error above
pip install -r my_package.whl

# correct: without -r
pip install my_package.whl

I hope this helps others who made the same little mistake as I did without noticing.

stefanbschneider
  • 5,460
  • 8
  • 50
  • 88