0

Такой код(я опустил некоторые части):

    import os
    path = 'C:\Users\Алекс\Desktop\DefendMySystem'    
    files = os.listdir(path)

В переменной path есть кириллица, вот что я получаю при выполнении сценария:

Traceback (most recent call last):
  File "main.py", line 116, in <module>
    main()
  File "main.py", line 99, in main
    files = os.listdir(path)
WindowsError: [Error 3] : 'C:\\Users\\\xd0\xa1\xd0\xb0\xd1\x88\xd0\xb0\\Desktop\
\DefendMySystem/*.*'

Как это можно исправить?

1 Answers1

2

С кодировками вечно какие-нибудь проблемы. Видимо, питон не справляется с угадыванием кодировки байтовой строки и не может корректно перевести её в кодировку файловой системы Windows.

Но в Python 2 у os.listdir (и некоторых других функций) есть особенность: если передать юникодную строку, то вернётся юникодный результат. При использовании юникода питон справляется с кодированием чего надо в какую надо кодировку, и никаких проблем нет.

Но начнём с того, что символ \ в строках является спецсимволом, и его нельзя ставить просто так. Его нужно экранировать так:

path = 'C:\\Users\\Алекс\\Desktop\\DefendMySystem'

или так:

path = r'C:\Users\Алекс\Desktop\DefendMySystem'

Сейчас path это байтовая строка, а для максимально корректной работы нужна юникодная. Строковый литерал можно сделать юникодым с помощью u'':

# -*- coding: utf-8 -*-
# вот этот ↑ комментарий должен стоять в первой строке файла!
path = u'C:\\Users\\Алекс\\Desktop\\DefendMySystem'
path = ur'C:\Users\Алекс\Desktop\DefendMySystem'

(Естественно, сам файл в таком случае тоже должен быть сохранён в кодировке UTF-8, желательно без BOM.)

Если это не строковый литерал, то можно декодировать байтовую строку в юникодную, если известна кодировка:

path = path.decode('utf-8')

Теперь, когда юникодная строка получена, os.listdir будет работать без проблем:

print(type(path))  # → unicode
files = os.listdir(path)  # type: List[unicode]

А вот в Python 3 все строки юникодные, и там подобных проблем в принципе не бывает (кроме совсем уж специфических случаев).

Поддержка Python 2.7 закончится в 2020 году.

andreymal
  • 13,178
  • не стоит про "угадывания" говорить (не только для байтовых, но и для Unicode строк не работало бы также, если бы исходный код интерпретировался бы, используя неверную кодировку)¶ Чтобы использовать не-ascii символы в исходном коде Питона, достаточно указать кодировку (наверху, как у вас явно в ответе показано) и не менее важно сохранить файл (исходный код) именно в этой кодировке (то есть если utf-8 указано, то не следует в блокноте в cp1251 сохранять -- получатся кракозябры)¶ Совершенно верно, что на Windows стоит Unicode для путей использовать. – jfs Aug 29 '18 at 18:41