Я пытаюсь вставить несколько строк импорта в исходный файл Python, но в идеале я хотел бы разместить их сразу после исходной строки документации. Скажем, я загружаю файл в строковую переменную следующим образом:
lines = open('filename.py').readlines()
Как найти номер строки, на которой заканчивается строка документации?
Нет, PEP8 не рекомендует этого, и на самом деле это сделает строки документации, а не строки документов. Строки документации являются только строками документации, когда они являются первым выражением в модуле, классе или функции. PEP8 говорит, что импорт должен происходить сразу после комментариев и строк документации.






Если вы используете стандартный формат строки документации, вы можете сделать что-то вроде этого:
count = 0
for line in lines:
if line.startswith ('"""'):
count += 1
if count < 3:
# Before or during end of the docstring
continue
# Line is after docstring
Может потребоваться некоторая адаптация для файлов без строк документации, но если ваши файлы отформатированы последовательно, это должно быть достаточно просто.
Не забывайте, что строка документации - это не просто строковый литерал, заключенный в тройные кавычки. Строка документации - это строковый литерал Любые, который является первым выражением в модуле, классе или функции. Он может использовать "" ", '' ',",' или даже r "" ", r '' ', r', r", u "" ", u '' ', u", u', ur "" ", ur '' ', ur" или ur' для вступительных цитат.
Вот что я имею в виду под «стандартным форматом строки документации» - в PEP 8 говорится об использовании трехстрочных литералов.
Даже со "стандартными" строками документации есть несколько хитрых вариантов. См. Рекомендации PEP257 по строкам документов в Юникоде и необработанных строках. Также существует общий случай однострочности, когда "" "не находится в начале строки. Также рассмотрите возможность использования строк документации со встроенными строками" "" с помощью экранирования (\ "" ")
Вместо того, чтобы использовать регулярное выражение или полагаться на определенное форматирование, вы можете использовать модуль токенизации python.
import tokenize
f=open(filename)
insert_index = None
for tok, text, (srow, scol), (erow,ecol), l in tokenize.generate_tokens(f.readline):
if tok == tokenize.COMMENT:
continue
elif tok == tokenize.STRING:
insert_index = erow, ecol
break
else:
break # No docstring found
Таким образом вы можете справиться даже с патологическими случаями, такими как:
# Comment
# """Not the real docstring"""
' this is the module\'s \
docstring, containing:\
""" and having code on the same line following it:'; this_is_code=42
точно так, как питон справился бы с ними.
Это функция, основанная на блестящем ответе Брайана, которую вы можете использовать для разделения файла на строку документации и код:
def split_docstring_and_code(infile):
import tokenize
insert_index = None
f = open(infile)
for tok, text, (srow, scol), (erow,ecol), l in tokenize.generate_tokens(f.readline):
if tok == tokenize.COMMENT:
continue
elif tok == tokenize.STRING:
insert_index = erow, ecol
break
else:
break # No docstring found
lines = open(infile).readlines()
if insert_index is not None:
erow = insert_index[0]
return "".join(lines[:erow]), "".join(lines[erow:])
else:
return "", "".join(lines)
Предполагается, что строка, завершающая строку документации, не содержит дополнительного кода за закрывающим разделителем строки.
Обратите внимание, что PEP8 рекомендует помещать импорт перед строками документации.