Как разбирать код Python, сохраняя строковые литералы такими, какие они есть?

Я пытаюсь просмотреть все строковые литералы в исходном коде Python, в то же время имея возможность определить, какой строковый литерал каждый из них.

К сожалению, как вы можете видеть в этом примере, ast.parse не работает:

[node.value.s for node in ast.parse('\'x\'; u\'x\'; b\'x\'; "x"; u"x"; b"x"').body]

Результат:

['x', 'x', b'x', 'x', 'x', b'x']

это означает, что я не могу различить литералы '' и u'' или '' и "" и т. д.

Как я могу разобрать исходный код Python, сохраняя при этом исходный литерал точно таким, как он написан?

Есть встроенный способ?

В соответствии с тем, как этот префикс u реализован в Python 3, как указано в ПЭП-0414, фактически нет никаких изменений во внутреннем представлении, поэтому то, что вы хотите, независимо от того, включал ли исходный синтаксис u или нет, не будет выражено или передано выйти из ast API.

metatoaster 28.05.2019 06:39

@metatoaster: Да, но есть ли другой API? Или для этого люди пишут свои лексеры/парсеры?

user541686 28.05.2019 06:40
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
2
102
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Информация, которую вы ищете, не является информацией уровня AST. Подходящим уровнем для проверки подобных вещей является уровень токена, и вы можете использовать для этого модуль tokenize.

API tokenize довольно неудобен — ему нужен ввод, который ведет себя как метод readline двоичного файлового объекта, поэтому вам нужно открывать файлы в двоичном режиме, и если у вас есть строка, вам нужно будет использовать encode и io.BytesIO для конвертации.

import tokenize
token_stream = tokenize.tokenize(input_file.readline)
for token in token_stream:
    if token.type == tokenize.STRING:
        do_whatever_with(token.string)

Вот версия Python 2 — имена функций другие, и вам нужно обращаться к информации о токенах позиционно, потому что вы получаете обычные кортежи вместо именованных кортежей:

import tokenize
token_stream = tokenize.generate_tokens(input_file.readline)
for token_type, token_string, _, _, _ in token_stream:
    if token_type == tokenize.STRING:
        do_whatever_with(token_string)

Вау спасибо!! Я совсем потерял надежду! Для тех, кто еще пытается разобрать строковый литерал, попробуйте list(tokenize.tokenize(io.BytesIO(b'\'x\'; u\'x\'; b\'x\'; "x"; u"x"; b"x"').readline)) в Python 3 или list((lambda items: tokenize.tokenize(io.BytesIO(b'\'x\'; u\'x\'; b\'x\'; "x"; u"x"; b"x"').readline, lambda *args: items.append(args)) and None or items)([])) в Python 2.

user541686 28.05.2019 06:56

@Mehrdad: для Python 2 вы должны использовать tokenize.generate_tokens вместо tokenize.tokenize. Они переименовали функции в Python 3. (Кроме того, Python 2 предоставляет обычные кортежи вместо именованных кортежей, поэтому вам нужно обращаться к элементам позиционно.)

user2357112 supports Monica 28.05.2019 07:01

Да, я только что заметил это несколько секунд назад :) спасибо!

user541686 28.05.2019 07:02

Другие вопросы по теме