Błąd składni: znak inny niż ASCII „xa3” w pliku, gdy funkcja zwraca „£”


284

Powiedz, że mam funkcję:

def NewFunction():
    return '£'

Chcę wydrukować coś ze znakiem funta przed nim i wyświetla błąd podczas próby uruchomienia tego programu, ten komunikat o błędzie jest wyświetlany:

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

Czy ktoś może mi powiedzieć, w jaki sposób mogę dołączyć znak funta do funkcji zwrotu? Zasadniczo używam go na zajęciach, a '__str__'znak funta jest objęty częścią.


43
Czy w ogóle czytałeś PEP, z którym się łączysz? Opisuje na czym polega problem i jak go naprawić.
murgatroid99

2
„Czy ktoś może poinformować mnie, w jaki sposób mogę dołączyć znak funta do mojej funkcji powrotu”. Cóż, komunikat o błędzie mówi „zobacz szczegóły w python.org/peps/pep-0263.html ”; może powinieneś zacząć od tego?
Karl Knechtel

5
@ murgatroid99 Oto, czego ty i w czasie, gdy piszę 27 innych, brakuje: Tak, oczywiście, przeczytam PEP. Poziom trudności: próbowałem uruchomić / bin / sh przeciwko kontenerowi dokowanemu. Nie próbuję jawnie uruchamiać Pythona. Więc wszystko, co PEP powie mi, to jak naprawić kod Pythona, którego nie próbuję uruchomić i nie napisałem. Miałem nadzieję na więcej kontekstu od StackOverflow, zamiast tego dostałem zadowolenie z siebie. :( Dalsze poszukiwanie okazało się rzeczywistą odpowiedź: stackoverflow.com/questions/38992850/... - Zauważ, że PEP zrobił dokładnie zera do pomocy.
Mark Allen

@ MarkAllen - w połączonej odpowiedzi komunikat o błędzie wskazuje, że python próbuje zinterpretować „/ bin / bash” - to wprawdzie coś łatwego do przeoczenia, ale nic w tym pytaniu nie wskazuje, że ma to związek z dokerem lub kontenerem, więc rada tutaj, jak odkryłeś, nie dotyczy twojego problemu - to nie jest zadowolenie z siebie, tylko to, że w twoim problemie jest kontekst, którego tu nie ma.
tanantish

@tanantish Stoję za tym, co powiedziałem. Mam błąd w pytaniu. Zamiast podawać przydatne informacje ludziom, z którymi się spotkałeś: „Czy w ogóle czytałeś PEP, z którym łączyłeś?” i „No cóż, komunikat o błędzie mówi, patrz (bla), może powinieneś zacząć od tego?” <- Te odpowiedzi nie są pomocne. Nie jestem pewien, dlaczego prowadzimy tę dyskusję.
Mark Allen

Odpowiedzi:


368

Polecam przeczytać PEP, który daje błąd. Problem polega na tym, że Twój kod próbuje użyć kodowania ASCII, ale symbol funta nie jest znakiem ASCII. Spróbuj użyć kodowania UTF-8. Możesz zacząć od umieszczenia # -*- coding: utf-8 -*-na górze pliku .py. Aby uzyskać bardziej zaawansowane, możesz również zdefiniować kodowanie w łańcuchach po łańcuchach w kodzie. Jeśli jednak próbujesz umieścić literę znaku funta w kodzie, potrzebujesz kodowania, które obsługuje go dla całego pliku.


306

Dodanie następującego dwóch wierszy było na górze mojego skryptu .py dla mnie zadziałało (potrzebna była pierwsza linia):

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

Mam ten sam problem, a mój Python to 2.7.11. Po dodaniu drugiego wiersza # -*- coding: utf-8 -*-na początku pliku rozwiązał problem.
hailong

2
Pierwszy wiersz to wykonanie pliku py na * nix. To nie jest tak naprawdę związane z tym pytaniem.
cmd,

57

Najpierw dodaj # -*- coding: utf-8 -*-linię na początku pliku, a następnie użyj u'foo'dla wszystkich danych Unicode innych niż ASCII:

def NewFunction():
    return u'£'

lub użyj magii dostępnej od Pythona 2.6, aby uczynić ją automatyczną:

from __future__ import unicode_literals

12
Jeśli tak # -*- coding: utf-8 -*-, nie musisz poprzedzać ciągów znaków Unicode słowemu
Daniel Lee

@plaes co z tego, jeśli jest na zmiennej? przykład czytając plik? Nie mogę używać uVariable, jak to zrobić?
Skizo-ozᴉʞS

1
@DanielLee Tyle, że to nieprawda. # -*- coding: utf-8 -*-następnie print 'błąd'będzie wyświetlał śmieci, podczas gdy print u'błąd'działa.
Przemek D

@DanielLee Co powiedział Przemek D. Umieszczanie literałów UTF-8 w kodzie źródłowym w ten sposób nie jest ogólnie dobrym pomysłem i może prowadzić do niepożądanych zachowań, szczególnie w Pythonie 2. Jeśli literały nie są czystym 7-bitowym ASCII, powinny to być rzeczywiste Unicode, a nie UTF-8, więc w Python 2 powinieneś umieścić uprefiks na takich literałach. W Pythonie 3 zwykłe ciągi znaków są w każdym razie Unicode, ale uw najnowszych wersjach Pythona 3 jest dozwolony prefiks, aby ułatwić pisanie kodu, który zachowuje się poprawnie zarówno w Pythonie 2, jak i 3.
PM 2Ring,

12

Komunikat o błędzie mówi dokładnie, co jest nie tak. Interpreter języka Python musi znać kodowanie znaku spoza ASCII.

Jeśli chcesz zwrócić U + 00A3 , możesz powiedzieć

return u'\u00a3'

który reprezentuje ten znak w czystym ASCII za pomocą sekwencji ucieczki Unicode. Jeśli chcesz zwrócić ciąg bajtów zawierający bajt dosłowny 0xA3, to jest

return b'\xa3'

(gdzie w Pythonie 2 bjest to domniemane, ale jawne jest lepsze niż niejawne).

Połączony PEP w komunikacie o błędzie instruuje dokładnie, jak powiedzieć Pythonowi „ten plik nie jest czystym ASCII; oto kodowanie, którego używam”. Jeśli tak, kodowanie to UTF-8

# coding=utf-8

lub kompatybilny z Emacs

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

Jeśli nie wiesz, jakiego kodowania używa Twój edytor do zapisania tego pliku, sprawdź go za pomocą edytora szesnastkowego i googlingu. Przepełnienie stosutag ma stronę informacyjną tagu z dodatkowymi informacjami i poradami dotyczącymi rozwiązywania problemów.

W wielu słowach poza 7-bitowym zakresem ASCII (0x00-0x7F) Python nie może i nie może zgadywać, jaki ciąg reprezentuje sekwencja bajtów. https://tripleee.github.io/8bit#a3 pokazuje 21 możliwych interpretacji bajtu 0xA3, a to tylko ze starszych 8-bitowych kodowań; ale równie dobrze może to być pierwszy bajt kodowania wielobajtowego. Ale tak naprawdę sądzę, że używasz Latin-1, więc powinieneś

# coding: latin-1

jako pierwszy lub drugi wiersz pliku źródłowego. W każdym razie bez wiedzy o tym, jaki charakter ma reprezentować bajt, człowiek nie byłby w stanie zgadnąć.

Zastrzeżenie: na coding: latin-1pewno usunie komunikat o błędzie (ponieważ nie ma sekwencji bajtów, które nie są technicznie dozwolone w tym kodowaniu), ale może dać całkowicie niepoprawny wynik, gdy kod jest interpretowany, jeśli rzeczywiste kodowanie jest czymś innym. Naprawdę musisz znać kodowanie pliku z całkowitą pewnością, kiedy deklarujesz kodowanie.


Jest to dostosowanie wcześniejszej odpowiedzi mojej do duplikatu pytania: stackoverflow.com/a/50829958/874188
tripleee

Python 3 domyślnie ustawiony jest na UTF-8 dla plików źródłowych i prawdopodobnie powinieneś używać UTF-8 do wszystkiego w dzisiejszych czasach. utf8everywhere.org
tripleee

8

Dodanie następujących dwóch wierszy w skrypcie rozwiązało problem.

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

Mam nadzieję, że to pomoże !


2

Prawdopodobnie próbujesz uruchomić plik Python 3 za pomocą interpretera Python 2. Obecnie (od 2019 r.) Domyślną pythonkomendą jest Python 2, gdy obie wersje są zainstalowane, w systemie Windows i większości dystrybucji Linuksa.

Ale jeśli rzeczywiście pracujesz nad skryptem Python 2, jeszcze nie wspomnianym rozwiązaniem na tej stronie jest ponowne zapisanie pliku w kodowaniu BOM UTF-8 +, który doda trzy specjalne bajty na początku pliku, będą one jawnie poinformuj interpreter języka Python (i Twój edytor tekstu) o kodowaniu plików.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.