global
лучше объявить глобальный объект и спрятать flag
в него:class PortScanner:
def __init__(self):
self.flag = 0
def animate_menu_up(self):
print("\n")
...
self.flag = 1
__init__()
глобального объекта. И основной цикл вынести в отдельный метод, например, run()
. Тогда на нижнем уровне у нас останется что-то вроде:import ...
class PortScanner:
...
if __name__ == '__main__':
main_obj = PortScanner()
main_obj.run()
def animate_menu_up():
""" Создание красивого меню (вверх). """
while True:
в select_mode()
,MF_INITIAL = 0
MF_MENU_CENTER = 1
MF_MENU_DOWN = 2
MF_SELECT = 3
SCREEN_WIDTH = 50
ALL_PORTS = [22, 80, 7777, 2516]
SOCK_TIMEOUT = 0.5
ANIM_SYMBOL = '~'
ANIM_DELAY = 0.02
except RuntimeError:
continue
если вы действительно хотите продолжить выполнение программы после такой ошибки (что в обычных обстоятельствах бессмысленно и опасно), то позаботьтесь хотя бы о правильной индикации:import traceback
...
except RuntimeError:
traceback.print_exc(file=sys.stdout)
continue
while True:
try:
{
MF_MENU_CENTER: th_three.start,
MF_MENU_DOWN: th_two.start,
MF_SELECT: select_mode,
}[flag]()
except RuntimeError:
traceback.print_exc(file=sys.stdout)
continue
Такой наивный подход выводит много шелухи на экран, но это не важно. Важно то, что такой код проще читать и дорабатывать, чем цепочку if...elif...else
.def animate_menu_center():
""" Создание анимации центрального меню. """
# настройки для анимации
output_strings = [
'[1] scan all ports',
'[2] scan enter port',
'[3] exit',
'SCANNER V1.0',
]
# анимация названия
for output_string in output_strings:
print('\r\t\t', end='')
for ch in output_string:
print(ch, end='')
time.sleep(ANIM_DELAY)
# last string?
if output_string != output_strings[-1]:
# new line
print()
print('', flush=True)
flag = MF_MENU_DOWN
(Я убрал цвета для простоты.)# TODO: реализовать режим '2' (скан произвольного списка портов)
Это однозначно плюс − показывает, что вы умеете работать в команде и пользоваться системами контроля версий.pip
и setuptools
. Вот хороший гайд, можете пропустить часть “Uploading the distribution archives” и далее, если не хотите делать ваши пакеты общедоступными. И не забывайте про pip install -e
. Car.__init__(self)
.super()
возвращет класс, ближайший к текущему согласно MRO. Вот вроде неплохая статья на русском: https://habr.com/post/62203/. call_func = input("Введите название функции чтобы её вызвать: ")
locals()[call_func]()
call_func
. Если они определены в неймспейсе модуля, а call_func
− глубже, в функции или методе, то поможет globals()
. А если они вообще где-то в других модулях, которые могут не быть импортированы заранее, то нужно копать в сторону importlib.import_module
, но это уж точно оверкилл.eval
, но тоже нехорошо.