Сделайте так, чтобы flake8 различал неопределенные функции и звездный импорт.

У меня есть довольно большой проект, который я пытаюсь очистить перед публикацией, но когда я запускаю flake8, я получаю тонны

'F405 <function> may be undefined, or defined from star imports: generic_functions`

Я мог бы избежать этого, заменив строку:

from generic_functions import *

в начале моего файла, но:

  1. Я буквально использую все функции там, поэтому я не понимаю, как более питонически превышать ограничение в 80 символов, печатая каждую функцию:

     from generic_functions import (function1, function2, function3, function4, function5, function6, function7...)
    
  2. Выполнение вышеуказанного было бы утомительным, особенно если мне нужно добавить или удалить из десятков функций в generic_functions.py.

Другой вариант — отключить предупреждение F405, но что, если функция действительно не определена? Было бы неплохо разрешить импорт звездочек, но при этом ловить что-то неопределенное. Есть ли способ сделать это? Я попытался добавить # noqa в строку импорта, но это не помогло.


person SurpriseDog    schedule 22.05.2019    source источник


Ответы (2)


Вы можете сделать следующее:

  1. Оставьте свой импорт как from generic_functions import *
  2. Запустите flake8 как flake8 --ignore=F405 file.py. Я действительно не знаю, почему # noqa не работает, а --ignore работает.
  3. Проверьте остальные возможные ошибки с помощью pylint. Pylint может определить, что <function> определено и импортировано из generic_functions.
person sanyassh    schedule 22.05.2019
comment
Считается ли дурным тоном оставлять строку from generic_functions import * при использовании всех функций? Я искал этот вопрос в Интернете и вижу много ненависти к звездному импорту. - person SurpriseDog; 23.05.2019

Вы можете использовать pylint, чтобы определить, какие функции требуются, а какие нет. Я написал функцию для автоматизации этого процесса. Это работает следующим образом:

  1. Запустите pylint для скрипта и сопоставьте все ошибки W0614: Unused import.
  2. Получить список переменных в целевом модуле с помощью vars()
  3. Возьмите разницу этих наборов и верните только то, что можно импортировать.

import subprocess, types

def scrape_wildcard(filename, modvars):
    "Get variables imported from module in wild * import"
    error = "W0614: Unused import "
    unused = []
    for line in quickrun(['pylint', filename]):
        if error in line:
            unused.append(line.split(error)[1].split()[0])

    out = dict()
    for name in set(modvars.keys()) - set(unused):
        if not name.startswith('__'):
            func = modvars[name]
            if not isinstance(func, types.ModuleType):
                out[name] = modvars[name]
    return out


def quickrun(cmd, check=False, encoding='utf-8', errors='replace'):
    ret = subprocess.run(cmd, stdout=subprocess.PIPE, check=check)
    return ret.stdout.decode(encoding=encoding, errors=errors).splitlines()


import ????? as mymod
filename = "?????"
print('from', mymod.__name__, 'import', ', '.join(scrape_wildcard(filename, vars(mymod)).keys()))
'''

Заменить ????? с именем вашего модуля и именем файла модуля соответственно.

person SurpriseDog    schedule 15.04.2021