Как определить, есть ли в строке Python комментарий, и разбить строку на `[code, comment]`

Мне интересно, как

  1. определить (True / False), есть ли в строке кода Python комментарий
  2. разделить строку на code, comment

Что-то вроде:

      loc_1 = "print('hello') # this is a comment"

Это очень просто, но что-то вроде:

      loc_2 = for char in "(*#& eht # ": # pylint: disable=one,two # something

Не все так однозначно. Я вообще не знаю, как это сделать, так что могу

      f(loc_2)
# returns
[
    # code
    'for char in "(*#& eht # ":',
    # comment
    ' # pylint: disable=one,two # something'
]

Из комментариев: «Вы отметили это с помощью libcst. Вы уже использовали эту библиотеку, чтобы предоставить вам AST?»

Я пытался использовать это и не смог, например:

Из комментариев: « Вы разбираете только отдельные строки, исходный код функции или класса или анализируете целые модули? »

Я разбираю отдельные строки - по крайней мере, это было моим намерением. Я хотел иметь возможность перебирать строки в файле. У меня есть уже существующий процесс, который уже выполняет итерацию по строкам файла python, но я хотел расширить его, чтобы учесть комментарии, которые мотивировали этот вопрос.

Из комментариев «Какова ваша конечная цель с результатами синтаксического анализа, просто получить исходный код без комментариев?»

Нет - мне нужен исходный код и комментарий, как в примере.

1 ответ

Я думаю, вы можете найти ответ, используя io.StringIO() а также tokenize.generate_tokens(). Если применить к строке, представляющей строку Python, вы должны получить список tokeninfo который вы затем можете проверить на предмет токена комментария ( tokenize.COMMENT).

Ваш метод может выглядеть примерно так, но, пожалуйста, сделайте имя значимым, а не f()

      import io
import tokenize

def separate_code_from_comments(text):
    reader = io.StringIO(text).readline
    comment_tokens = (t for t in tokenize.generate_tokens(reader) if t.type == tokenize.COMMENT)
    comment = next(comment_tokens, None)
    return [text[0: comment.start[1]], text[comment.start[1]:]] if comment else [text, '']

print(separate_code_from_comments("print('hello') # this is a comment"))
print(separate_code_from_comments("# this is a comment"))
print(separate_code_from_comments("loc_2 = for char in \"(*#& eht #\": # pylint: disable=one,two # something"))
print(separate_code_from_comments("loc_2 = for char in \"(*#& eht #\": "))

Это должно распечатать:

      ["print('hello') ", '# this is a comment']
['', '# this is a comment']
['loc_2 = for char in "(*#& eht #": ', '# pylint: disable=one,two # something']
['loc_2 = for char in "(*#& eht #": ', '']
Другие вопросы по тегам