Artikelverzeichnis
Vorwort
Heute möchte ich etwas sehr Seltsames mitteilen: Beim Schreiben von Code bin ich auf unsichtbare Zeichen gestoßen! ! !
1. Ursache
Heute habe ich plötzlich eine Fehlermeldung erhalten, als ich pipreqs
die Bibliotheken verwendet habe, auf die ich zum Exportieren des Projekts angewiesen war:
pipreqs . --encoding=utf-8 --force
# 以下是报错信息
ERROR: Failed on file: ./build.py
Traceback (most recent call last):
File "/usr/local/bin/pipreqs", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python3.8/dist-packages/pipreqs/pipreqs.py", line 528, in main
init(args)
File "/usr/local/lib/python3.8/dist-packages/pipreqs/pipreqs.py", line 455, in init
candidates = get_all_imports(input_path,
File "/usr/local/lib/python3.8/dist-packages/pipreqs/pipreqs.py", line 131, in get_all_imports
raise exc
File "/usr/local/lib/python3.8/dist-packages/pipreqs/pipreqs.py", line 117, in get_all_imports
tree = ast.parse(contents)
File "/usr/lib/python3.8/ast.py", line 47, in parse
return compile(source, filename, mode, flags,
File "<unknown>", line 1
# -*- coding:utf-8 -*-
^
SyntaxError: invalid character in identifier
Als ich direkt kam SyntaxError
, #
stellte sich heraus, dass es sich um einen ungültigen Charakter handelte. Der Charakter #
bedeutete, dass er sehr unschuldig war, und die betroffene Person war sehr schockiert! ! ! Ist das nicht ein tolles Zeichen dafür, die Welt zu verlassen, und ein toller Witz darüber, in die Welt hineinzuschlüpfen? ? ? Dies ist nur eine Zeile Codekommentar, wie könnte das schief gehen!
2. Untersuchung
Als ich zum ersten Mal auf so etwas Böses stieß, überprüfte ich den pipreqs
Quellcode. Der Code war sehr einfach, also habe ich den Teil extrahiert, der den Fehler gemeldet hat:
# pipreqs/pipreqs.py line 112
for file_name in files:
file_name = os.path.join(root, file_name)
with open(file_name, "r", encoding=encoding) as f:
contents = f.read()
try:
tree = ast.parse(contents) # 在这里报错了
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for subnode in node.names:
raw_imports.add(subnode.name)
elif isinstance(node, ast.ImportFrom):
raw_imports.add(node.module)
except Exception as exc:
...
Die Bedeutung ist ebenfalls leicht zu verstehen: Lesen Sie alle Dateien pipreqs
im aktuellen Projekt und führen Sie dann mithilfe der Bibliothek eine Syntaxanalyse durch, um den Bibliotheksnamen zu erhalten, von dem die Datei abhängt. Da dieser Teil einen Fehler meldete, habe ich ihn direkt herausgenommen. Zu diesem Zeitpunkt hatte ich den starken Verdacht, dass etwas Ernstes vorlag !python
ast
python
ast
bug
3. Hohe Energie
Um zu bestätigen, dass ast
beim Parsen der Datei ein Fehler aufgetreten ist, habe ich alle python
Dateien im aktuellen Projekt einzeln getestet. Die Entwicklung hat jedoch meine Erwartungen übertroffen: Die zweite Datei (process_data.py)
konnte analysiert werden!
Ich habe mir diese Datei angesehen und festgestellt, dass sie am Anfang denselben Kommentar enthält, aber es wurde kein Fehler gemeldet. Gibt es ein Problem mit der Kodierung? Ich habe es geöffnet Pycharm
und einen Blick darauf geworfen, und es gab kein Problem:
Das war zu seltsam, also habe ich es debug
noch einmal überprüft und mir den Inhalt der Datei angesehen, um sicherzustellen, dass nichts falsch war:
Ich konnte es nicht herausfinden, also fragte ich ChatGPT
:
Es wurden vier Zweifelspunkte vergeben, die grundsätzlich nacheinander beseitigt wurden. python 3.8
Die Dateien waren utf-8
kodiert, es gab keine Grammatikfehler und es gab keine Probleme mit den Kommentaren. Aber eines verstehe ich nicht: unsichtbare Sonderzeichen?
Unsichtbar? Da es sich um ein Zeichen handelt, muss es einen Platz haben, auch wenn es nicht sichtbar ist. Dann passierte das Seltsamste:
Es gibt wirklich ein Nullzeichen an der ersten Position, dies. . . Können leere Zeichen trotzdem Platz beanspruchen?
Nachdem ich es gedruckt hatte ASCII
, stellte ich fest, dass der Wert lautete 65279
und das leere Zeichen tatsächlich ASCII
einen Wert hatte. Ich hatte plötzlich das Gefühl, dass dieses Problem nicht einfach war. Ist es wirklich unsichtbar?
4. Beseitigen Sie Verwirrung
Baidu hat einen Blick darauf geworfen und festgestellt, dass ASCII
der Wert 65279
durch die in der Datei verwendete Codierung verursacht wird UTF-8 BOM
. Dies ist Windows
die Standardcodierungsmethode beim Erstellen von Dateien in der Umgebung. Ich habe mir das auch speziell angesehen und festgestellt, dass es sich tatsächlich um Folgendes handelt:
Diese Einstellung gibt es auch in Pycharm
. Standardmäßig Pycharm
wird die Codierung beim Erstellen neuer Dateien in verwendet UTF-8 with NO BOM
, was oft gesagt wird UTF-8
. Der Grund, warum ast
einige Bibliotheken Dateien normal analysieren können und andere nicht, liegt darin, dass einige Dateien möglicherweise nicht in Pycharm
Erstellt in sind, was dazu führte zu dieser seltsamen Zeit, die passiert. Gleichzeitig habe ich die Datei im Binärmodus gelesen und festgestellt, dass die ersten drei Bytes \xEF\xBB\xBF
, die UTF-8 BOM
beim Codieren automatisch hinzugefügt wurden.
py_file = './build.py'
with open(py_file, 'r', encoding='utf-8') as f:
contents = f.read()
if ord(contents[0]) == 65279:
print('UTF-8 BOM')
with open(py_file, 'rb') as f:
contents = f.read(3)
if contents == b'\xEF\xBB\xBF':
print('UTF-8 BOM')
# UTF-8 BOM
# UTF-8 BOM
Also habe ich die Dateikodierung von auf UTF-8 BOM
geändert UTF-8
und das Problem war gelöst!
Folgen Sie dem öffentlichen WeChat-Konto:
夏小悠
um weitere Artikel, ArtikelPPT
und andere Informationen zu erhalten ^_^