Поиск модулей Python, содержащих символы, отличные от ASCII

У меня есть проект Python, содержащий сотни модулей. В Python 2.6 кодировка исходных файлов (модулей) должна быть ASCII, если не присутствует явное объявление кодировки. Есть ли простой способ узнать, какие модули Python содержат символы, отличные от ASCII? Чтобы я мог их исправить.

С уважением,


person alwbtc    schedule 11.08.2011    source источник


Ответы (3)


Взгляните на пакет Python chardet. Вы можете использовать тот же подход os.walk, что и agf, и вызывать метод chardet.detect и помечать файлы, которые не являются ASCII (или с более низким значением достоверности).

Тем не менее, это оставляет место для ошибки, поэтому, если вы хотите быть более уверенным, вы также можете сканировать каждый файл на наличие символов, которые вряд ли появятся в файле python (без букв, без знаков препинания и т. д.). Однако это не обнаружит такие вещи, как символы UTF-16, которые имеют то же значение, что и два 7-битных, дополненных нулями символов ascii, т. е. U+16705 ‹--> AA.

Тем не менее, если символы, которые вы хотите исключить, относятся к ограниченному числу наборов символов, вы сможете найти их с высокой степенью уверенности.

person Dana the Sane    schedule 11.08.2011

open(filename).read().decode("ascii")

Если это вызывает UnicodeDecodeError, у вас есть некоторые символы, отличные от ascii.

Как говорит Дана, этого недостаточно, чтобы гарантировать, что файл не является UTF-16 или подобным.

person John La Rooy    schedule 11.08.2011

Не очень быстро, но сработает. Он будет работать для любой кодировки, совместимой с ASCII, такой как UTF-8, Latin-1 и т. д., но не для UTF-16.

def find_non_ascii(packagedir):
    for filepath in os.walk(packagedir):
        if not filepath[-1].endswith('.py'):
            continue
        filepath = os.path.join(*filepath)
        for line in open(filepath):
            for char in line:
                if ord(char) > 127:
                    yield filepath
                    doublebreak = True
                    break
            else:
                doublebreak = False
            if doublebreak:
                break

or

def find_non_ascii(packagedir):
    for filepath in os.walk(packagedir):
        if not filepath[-1].endswith('.py'):
            continue
        filepath = os.path.join(*filepath)
        try:
            open(filepath, 'rb').read().decode('ascii')
        except:
            yield filepath

Изменить: эта вторая версия, вероятно, быстрее.

person agf    schedule 11.08.2011
comment
Я думаю, что тест ord(127) будет исключать только расширенные символы ascii. Существует пересечение между набором значений char в многобайтовых кодировках и значением двух последовательных 7-битных символов ascii. - person Dana the Sane; 11.08.2011