尝试在 Python 脚本中使用非 ASCII 文本时出现“SyntaxError:非 ASCII 字符 ...”或“SyntaxError:以 ... 开头的非 UTF-8 代码”

2024-12-05 08:38:00
admin
原创
164
摘要:问题描述:我在 Python 2 中尝试过这个代码:def NewFunction(): return '£' 但我收到一条错误消息:SyntaxError: Non-ASCII character 'xa3' in file '...' but no encoding declared; see h...

问题描述:

我在 Python 2 中尝试过这个代码:

def NewFunction():
    return '£'

但我收到一条错误消息:

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

类似地,在 Python 3 中,如果我编写相同的代码并使用 Latin-1 编码保存,我会得到:

SyntaxError: Non-UTF-8 code starting with 'xa3' in file ... on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

如何在代码中的字符串文字中使用井号?


另请参阅:定义 Python 源代码编码的正确方法,了解有关是否需要编码声明以及应如何编写的详细信息。请使用该问题关闭有关如何编写声明的重复问题,并使用这个问题关闭有关解决错误的问题。


解决方案 1:

我建议你阅读错误提示的 PEP。问题是你的代码试图使用 ASCII 编码,但磅号不是 ASCII 字符。尝试使用 UTF-8 编码。你可以从# -*- coding: utf-8 -*-.py 文件顶部开始。为了更高级,你还可以在代码中逐个字符串定义编码。但是,如果你试图将磅号文字放入代码中,则需要一种支持整个文件的编码。

解决方案 2:

在我的 .py 脚本顶部添加以下两行对我有用(第一行是必要的):

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

解决方案 3:

首先将该# -*- coding: utf-8 -*-行添加到文件开头,然后将其u'foo'用于所有非 ASCII unicode 数据:

def NewFunction():
    return u'£'

或者使用 Python 2.6 以来可用的魔法来使其自动化:

from __future__ import unicode_literals

解决方案 4:

错误信息会告诉你具体哪里出了问题。Python 解释器需要知道非 ASCII 字符的编码。

如果你想返回U+00A3,那么你可以说

return u'/u00a3'

它通过 Unicode 转义序列以纯 ASCII 表示此字符。如果你想返回一个包含文字字节 0xA3 的字节字符串,那就是

return b'xa3'

(其中在 Python 2 中b是隐式的;但是显式比隐式更好)。

错误消息中链接的 PEP 会指导您如何告诉 Python“此文件不是纯 ASCII;这是我正在使用的编码”。如果编码是 UTF-8,则

# coding=utf-8

或 Emacs 兼容的

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

如果你不知道你的编辑器使用哪种编码来保存此文件,请使用十六进制编辑器之类的工具和谷歌搜索来检查它。 Stack Overflow字符编码标签有一个标签信息页面,其中包含更多信息和一些故障排除提示。

简而言之,在 7 位 ASCII 范围(0x00-0x7F)之外,Python 无法也不应该猜测字节序列代表什么字符串。https: //tripleee.github.io/8bit#a3显示了字节 0xA3 的 21 种可能解释,这仅来自传统的 8 位编码;但它也可能是多字节编码的第一个字节。但事实上,我猜你实际上使用的是 Latin-1,所以你应该有

# coding: latin-1

作为源文件的第一行或第二行。无论如何,如果不知道该字节应该代表哪个字符,人类也无法猜出这一点。

需要注意的是:coding: latin-1肯定会删除错误消息(因为此编码中不存在技术上不允许的字节序列),但如果实际编码是其他编码,则在解释代码时可能会产生完全错误的结果。声明编码时,您确实必须完全确定文件的编码。

解决方案 5:

在脚本中添加以下两行可以解决我的问题。

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

希望有帮助!

解决方案 6:

您可能正在尝试使用 Python 2 解释器运行 Python 3 文件。目前(截至 2019 年),python在 Windows 和大多数 Linux 发行版上,当两个版本都安装时,命令默认为 Python 2。

但是如果您确实在处理 Python 2 脚本,那么本页面尚未提及的解决方案是以 UTF-8+BOM 编码重新保存文件,这会在文件开头添加三个特殊字节,它们将明确地告知 Python 解释器(和您的文本编辑器)有关文件编码的信息。

解决方案 7:

概括

如果出现此错误,请使用编码声明来告诉 Python 源代码 (.py) 文件的编码。如果没有这样的声明,Python 3.x 将默认为 UTF-8;Python 2.x 将默认为 ASCII。声明看起来像一条注释,其中包含一个标签coding:,后跟有效文本编码的名称。所有 ASCII 透明编码均受支持。

例如:

#!/usr/bin/env python
# coding: latin-1

确保文件实际使用的编码,以便编写正确的编码声明。请参阅如何确定文本的编码以获取一些提示。或者,通过检查文本编辑器中的配置选项尝试使用不同的编码。

问题

计算机上的每个文件都是由原始字节组成的,即使文件以“文本模式”打开,这些字节本身也不是“文本” 。当文件应该表示文本时(例如 Python 程序的源代码),需要根据编码规则对其进行解释才能理解数据。

但是,没有明显的方法可以从文件外部指示 Python 源文件的编码 - 例如,import语法没有提供任何地方来编写编码名称(毕竟,它不一定从源文件导入)。因此,必须以某种方式由文件内容本身描述编码,并且 Python 需要一种方法来动态确定该编码。

为了以一致且可靠的方式完成这项工作,自 2.3 版起,Python 使用一个简单的引导过程来确定文件编码。该过程由 PEP 263描述:

  • 首先,Python 开始读取文件的原始字节。如果它以UTF-8 编码的字节顺序标记(字节0xEF 0xBB 0xBF)开头,则 Python 会丢弃这些字节并指出文件的其余部分应为 UTF-8。(以这种方式编写的文件有时被称为“utf-8-sig”编码。)仍会遵循其余过程,以检查是否存在不兼容的编码声明。

  • 接下来,Python 尝试使用默认编码(或 UTF-8,如果看到字节顺序标记)和通用换行符读取文件的接下来两行:

+ 如果第一行不是注释(请注意,shebang行在 Python 语法中也是注释),则对文件的其余部分使用默认编码。
+ 否则,如果第一行是*编码声明*(与特定正则表达式匹配的注释),则使用为文件其余部分声明的编码。
+ 否则,如果第二行是编码声明,则使用为文件其余部分声明的编码。
+ 否则,对文件的其余部分使用默认编码。
  • 如果文件以 UTF-8 字节顺序标记开头,并且发现除 UTF-8 之外的编码声明,则会引发异常。

Python 使用以下正则表达式检测编码声明:

^[     ]*#.*?coding[:=][     ]*([-_.a-zA-Z0-9]+)

这是故意允许的;它旨在匹配其他工具(例如 Vim 和 Emacs 文本编辑器)已经在使用的几个标准编码声明。

编码声明的语法也经过设计,因此只需要 ASCII 中可表示的字符。因此,可以使用任何“ASCII 透明”编码。默认编码也是 ASCII 透明的;因此,如果前两行包含编码声明,它将被正确读取,如果没有,则无论如何都会对文件的其余部分使用相同的(默认)编码。最终效果就像始终假设正确的编码一样,即使一开始并不知道它。很聪明,对吧?

但是,请注意,不支持 UTF-16 和其他非 ASCII 透明编码。在此类编码中,无法使用默认编码读取编码声明,因此无法处理。字节顺序标记也不能用于表示 UTF-16:它根本无法识别。似乎最初有计划支持这一点,但后来被放弃了。

Python 3.x

PEP 3120将默认编码更改为UTF-8。因此,源文件可以简单地使用 UTF-8 编码保存,根据 Unicode 标准包含任意文本,并且无需编码声明即可使用。纯 ASCII 数据也是有效的 UTF-8 数据,因此仍然没有问题。

如果必须使用不同的ASCII 透明编码(如 Latin-1 (ISO-8859-1) 或 Shift-JIS)来解释源代码,请使用编码声明。例如:

#!/usr/bin/python
# -*- coding: iso-8859-1 -*-
# Assuming the file is actually encoded in Latin-1,
# the text character here would be represented as a 0xff byte.
# This would not be valid UTF-8 data, so the declaration is necessary.
# or else a SyntaxError will occur.
# In UTF-8, the text would be represented as 0xc3 0xbf.
print('ÿ')
# Similarly, without the encoding declaration, this line would print ÿ instead.
print('ÿ')

Python 2.x

默认编码为ASCII£ 。因此,在源文件中写入任何非 ASCII 文本(例如 )时都需要编码声明。

请注意,无论源编码是什么,在 2.x 中使用 Unicode 文本仍需要 Unicode 文字。指定编码可以让 Python 2.x 解释'ÿ'为有效的源代码(并且为 Latin-1 输入正确指定 Latin-1,而不是 UTF-8,可以让它将该文本视为 而ÿ不是ÿ),但这仍然是一个字节文字(不幸的是称为str)。要创建实际的 Unicode 字符串,请确保使用u前缀或适当的“未来导入”:from __future__ import unicode_literals

(但是,为了使这样的字符串可打印,可能还需要做更多的事情,特别是在 Windows 上;而且还有很多其他事情可能出错。Python 3 自动修复了所有这些问题。对于任何因为不愿意明确指定编码而坚持使用古老的、不受支持的版本的人:重新考虑。“显式优于隐式”。从长远来看,3.x 的方式更容易、更令人愉快。)

其他解决方法

无论编码如何,Unicode 转义都可用于在字符串文字中包含任意 Unicode 字符:

>>> # With every supported source file encoding, the following is represented
>>> # with the same bytes in the source file, AND prints the same string:
>>> print('xf8/u86c7U0001f9b6')
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2804  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1713  
  项目管理中,项目延期是一个极为常见且棘手的问题,它不仅会打乱整个项目计划,还可能导致成本超支、客户满意度下降等一系列连锁反应。深入剖析项目延期的原因,对于项目管理者来说至关重要,这有助于提前预防和及时应对,确保项目能够按时交付。需求变更引发的延期需求变更在项目推进过程中屡见不鲜。客户可能在项目进行到一定阶段后,由于市场...
工程项目管理的主要特征   0  
  建设工程项目的成功离不开高效的团队协作与良好的沟通。在复杂的建设工程领域,涉及众多的参与方、繁杂的施工流程以及各种不可预见的因素,团队成员之间能否紧密协作、顺畅沟通,直接关系到项目的进度、质量和成本控制。有效的团队协作与沟通能够整合各方资源,发挥团队成员的专业优势,及时解决问题,确保项目按计划推进。因此,深入探讨建设工...
工程项目管理   0  
  建设项目管理涵盖众多环节,沟通技巧与团队协作犹如项目顺利推进的两翼,缺一不可。有效的沟通能确保信息准确、及时地在项目团队成员、利益相关者之间传递,避免误解与冲突;而良好的团队协作则能整合各方资源,发挥团队最大效能,提升项目的成功率。在建设项目管理的复杂环境中,深入探讨沟通技巧与团队协作的要点,对于项目管理者和参与者都具...
工程项目管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用