295
votes

Say I have a function:

def NewFunction():
    return '£'

I want to print some stuff with a pound sign in front of it and it prints an error when I try to run this program, this error message is displayed:

SyntaxError: Non-ASCII character '\xa3' in file 'blah' but no encoding declared;
see http://www.python.org/peps/pep-0263.html for details

Can anyone inform me how I can include a pound sign in my return function? I'm basically using it in a class and it's within the '__str__' part that the pound sign is included.

6
Did you even read the PEP you linked to? It describes what the problem is and how to fix it. - murgatroid99
"Can anyone inform me how I can include a pound sign in my return function." Well, the error message says "see python.org/peps/pep-0263.html for details"; perhaps you should start there? - Karl Knechtel
@murgatroid99 Here's what you and at the time I type this 27 others are missing: Yes of course I'll read the PEP. Difficulty level: I got this trying to run /bin/sh against a docker container. I'm not overtly trying to run Python. So all the PEP is going to tell me is how to fix the python code I'm not trying to run and didn't write. I was hoping for more context from StackOverflow, got smugness instead. :( Further searching turned up the actual answer: stackoverflow.com/questions/38992850/… - notice how the PEP did exactly zero to help. - Mark Allen
@MarkAllen - in your linked answer, the error message indicates that python is trying to interpret "/bin/bash" - it's admittedly something easy to overlook, but nothing in this question indicates it's to do with docker or a container, so the advice here as you've found doesn't apply to your problem - it's not smugness, it's just that there's context in your problem, that's not present here. - tanantish
@tanantish I stand by what I said. I got the error in the question. Rather than give useful information people this was met with, "Did you even read the PEP you linked to?" and, "Well the error message says see (blah), prehaps you should start there?" <-- Those responses aren't helpful. I'm not sure why we're having this discussion. - Mark Allen

6 Answers

378
votes

I'd recommend reading that PEP the error gives you. The problem is that your code is trying to use the ASCII encoding, but the pound symbol is not an ASCII character. Try using UTF-8 encoding. You can start by putting # -*- coding: utf-8 -*- at the top of your .py file. To get more advanced, you can also define encodings on a string by string basis in your code. However, if you are trying to put the pound sign literal in to your code, you'll need an encoding that supports it for the entire file.

325
votes

Adding the following two lines at the top of my .py script worked for me (first line was necessary):

#!/usr/bin/env python
# -*- coding: utf-8 -*- 
58
votes

First add the # -*- coding: utf-8 -*- line to the beginning of the file and then use u'foo' for all your non-ASCII unicode data:

def NewFunction():
    return u'£'

or use the magic available since Python 2.6 to make it automatic:

from __future__ import unicode_literals
12
votes

The error message tells you exactly what's wrong. The Python interpreter needs to know the encoding of the non-ASCII character.

If you want to return U+00A3 then you can say

return u'\u00a3'

which represents this character in pure ASCII by way of a Unicode escape sequence. If you want to return a byte string containing the literal byte 0xA3, that's

return b'\xa3'

(where in Python 2 the b is implicit; but explicit is better than implicit).

The linked PEP in the error message instructs you exactly how to tell Python "this file is not pure ASCII; here's the encoding I'm using". If the encoding is UTF-8, that would be

# coding=utf-8

or the Emacs-compatible

# -*- encoding: utf-8 -*-

If you don't know which encoding your editor uses to save this file, examine it with something like a hex editor and some googling. The Stack Overflow tag has a tag info page with more information and some troubleshooting tips.

In so many words, outside of the 7-bit ASCII range (0x00-0x7F), Python can't and mustn't guess what string a sequence of bytes represents. https://tripleee.github.io/8bit#a3 shows 21 possible interpretations for the byte 0xA3 and that's only from the legacy 8-bit encodings; but it could also very well be the first byte of a multi-byte encoding. But in fact, I would guess you are actually using Latin-1, so you should have

# coding: latin-1

as the first or second line of your source file. Anyway, without knowledge of which character the byte is supposed to represent, a human would not be able to guess this, either.

A caveat: coding: latin-1 will definitely remove the error message (because there are no byte sequences which are not technically permitted in this encoding), but might produce completely the wrong result when the code is interpreted if the actual encoding is something else. You really have to know the encoding of the file with complete certainty when you declare the encoding.

12
votes

Adding the following two lines in the script solved the issue for me.

# !/usr/bin/python
# coding=utf-8

Hope it helps !

5
votes

You're probably trying to run Python 3 file with Python 2 interpreter. Currently (as of 2019), python command defaults to Python 2 when both versions are installed, on Windows and most Linux distributions.

But in case you're indeed working on a Python 2 script, a not yet mentioned on this page solution is to resave the file in UTF-8+BOM encoding, that will add three special bytes to the start of the file, they will explicitly inform the Python interpreter (and your text editor) about the file encoding.