Обновлено для Python 3:
>>> 'Tannh‰user'.encode().decode('ascii', 'replace').replace(u'\ufffd', '_')
'Tannh___user'
Сначала мы создаем строку байтов, используя encode()
- по умолчанию используется кодек UTF-8. Если у вас есть строка байтов, то, конечно, пропустите этот шаг кодирования.
Затем мы конвертируем ее в «обычную» строку, используя кодек ascii.
При этом используется свойство UTF-8, согласно которому все не-ascii символы кодируются как последовательность байтов со значением> = 0x80.
Оригинальный ответ - для Python 2:
Как это сделать, используя встроенный str.decode
метод:
>>> 'Tannh‰user'.decode('ascii', 'replace').replace(u'\ufffd', '_')
u'Tannh___user'
(Вы получаете unicode
строку, поэтому конвертируйте ее в str
, если вам нужно.)
Вы также можете конвертировать unicode
в str
, поэтому один не-ASCII символ заменяется на ASCII. Но проблема в том, что unicode.encode
с replace
переводит не-ASCII символы в '?'
, поэтому вы не знаете, был ли знак вопроса там уже раньше; см. решение от Игнасио Васкеса-Абрамса.
Другой способ, используя ord()
и сравнивая значение каждого символа, если он вписывается в диапазон ASCII (0-127) - это работает для unicode
строк и для str
в utf-8, латинской и некоторых других кодировках :
>>> s = 'Tannh‰user' # or u'Tannh‰user' in Python 2
>>>
>>> ''.join(c if ord(c) < 128 else '_' for c in s)
'Tannh_user'