• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Зачем и boot.py, и main.py?

RotaryF

New member
Вот и я взглянул в сторону микроПитона, благо под рукой и ESP8266, и ESP32.
Успел и поиграться малость с лампочками+, даже некое подобие Cron(a) под свои нужды наваял.
Для более полного понимания "процесса" хочу выяснить нафиг такая 2х-ступенчатая процедура загрузки, зачем этой змейке 2 файла? Какая разница произведу ли я полную инициализацию своей системы только в boot.py или же задействую и boot.py, и main.py?
Ну да, гибче, а как эту улучшенную (по ср., скажем, с Lua-init) гибкость грамотно использовать?
Все равно хоть после программной перезагрузки, хоть после глубокого сна процедура одинакова - перезапускаются и boot.py, и main.py :confused:
 

nikolz

Well-known member
Вот и я взглянул в сторону микроПитона, благо под рукой и ESP8266, и ESP32.
Успел и поиграться малость с лампочками+, даже некое подобие Cron(a) под свои нужды наваял.
Для более полного понимания "процесса" хочу выяснить нафиг такая 2х-ступенчатая процедура загрузки, зачем этой змейке 2 файла? Какая разница произведу ли я полную инициализацию своей системы только в boot.py или же задействую и boot.py, и main.py?
Ну да, гибче, а как эту улучшенную (по ср., скажем, с Lua-init) гибкость грамотно использовать?
Все равно хоть после программной перезагрузки, хоть после глубокого сна процедура одинакова - перезапускаются и boot.py, и main.py :confused:
читайте документацию там все есть про "нафига"
 

__ab__

New member
читайте документацию там все есть про "нафига"
чтобы ответ был полезен, а не был просто троллингом, обычно дают ссылки или цитаты,, если упоминают документацию.
мне известно вот это место в документации 3. The internal filesystem — MicroPython 1.9.3 documentation
пункт 3.3
И документация в этом месте врет - main.py не и импортируется самим python - его надо явно импортировать из boot.py
Если знаете другое упоминание в документации, приведите ссылку пожалуйста.

Зачем все же это разделение? Чтобы стимулировать программиста не пытаться отъедать ресурсы прикладной логикой в случае, если необходимые системные функции не загрузились.

Я обычно меняю boot.py на вот такой:
Код:
import gc, webrepl, esp, network, json, os, time
MAIN=None

#В файле config.json держим логин и пароль сети
#{"wlan_pwd": "XXXX", "wlan": "XXXX"}

def init():
    global MAIN
    lst = os.listdir()
    if 'config.json' in lst:
        try:
            with open('config.json', 'r') as x:
                cfg = json.load(x)
        except:
            return

    if 'wlan' in cfg:
        wlan = network.WLAN(network.AP_IF)
        wlan.active(False)

        wlan = network.WLAN(network.STA_IF)
        wlan.active(True)
        wlan.connect(cfg['wlan'], cfg['wlan_pwd'])

        x = 0 # 10 секунд ждем соединения WiFi
        while x < 10:
            if wlan.isconnected():
                webrepl.start()
                break
            x += 1
            time.sleep(1)

    # если есть main пытаемся запустить
    if 'main.py' in lst:
        MAIN = __import__('main')
        lst = dir(MAIN)
        if 'init' in lst:
            MAIN.init()

esp.osdebug(None)
init()
gc.collect()
ну а в main и прочих модулях - логика, которая просто не сможет работать, ели не отработало то, что есть в boot
 

RotaryF

New member
чтобы ответ был полезен, а не был просто троллингом, обычно дают ссылки или цитаты,, если упоминают документацию
Вот, это уже больше похоже на ответ и желание помочь.
А предыдущее "по документации" смахивает на х.з., но с умным видом :cool:
 

RotaryF

New member
Думаю, что тему можно закрывать, но напоследок я скажу (на основании своего опыта). ;)
"Исторически так сложилось". Возможно, разработчики чего там замышляли для усиления безопасности системы, но толку от этого хрен да ни хрена.
boot.py "первоначально автоматически создается системой" и рекомендуют туда лишний раз не лезть (если вам ни приспичит поиграться с WEBrepl). При этом файл никак не защищен от изменений o_O, так что при желании(?) переносите туда весть свой функционал main.py, но традиции есть традиции - зачем их без надобности нарушать? Делайте основное управление своей системой в main.py и будет вам счастье.
Связка boot.py-main.py вполне себе работает (если не дергаться) и пусть себе работает :D
 

__ab__

New member
Более того, он вообще не будет работать, если не залить его в файл boot.py ;)
Не вижу большой проблемы в том, чтобы перед началом работы залить файлы boot и config...

а еще можно так:
Код:
if 'config.json' in lst:
        try:
            with open('config.json', 'r') as x:
                cfg = json.load(x)
        except:
            return
else:
        cfg = {}
 

apatrushev

New member
Так лучше, да. Просто "дурако-устойчивый код" это хорошо. Кто-то может залить его через webrepl, например, и ресетнуть девайс. После чего будет весьма удивлён. Я вот как-то так поправил ваш код. Теперь "экстренная связь" с устройством будет даже в случае проблем.
Я сам этот код лично ещё не проверил - проверю, удалю этот дисклеймер.
Код:
import gc, webrepl, esp, network, json, os, time

# config.json example
# {
#     "wlan": {"ssid": "XXX", "password": "XXX"},
#     "webrepl": {"port": "III", "password": "XXX"}
# }

def init():
    try:
        with open('config.json', 'r') as fd:
            cfg = json.load(fd)
    except (OSError, ValueError):
        return webrepl.start()

    webrepl_config = cfg.get('webrepl', {})
    webrepl.start(**webrepl_config)
    if 'wlan' in cfg:
        sta = network.WLAN(network.STA_IF)
        sta.active(True)
        sta.connect(cfg['wlan']['ssid'], cfg['wlan']['password'])
        while not sta.isconnected():
            time.sleep(0.1)
        webrepl.stop()
        ap = network.WLAN(network.AP_IF)
        ap.active(False)
        webrepl.start(**webrepl_config)

    if 'main.py' in os.listdir():
        main = __import__('main')
        lst = dir(main)
        if 'init' in lst:
            main.init()

esp.osdebug(None)
init()
gc.collect()
 

nikolz

Well-known member
Так лучше, да. Просто "дурако-устойчивый код" это хорошо. Кто-то может залить его через webrepl, например, и ресетнуть девайс. После чего будет весьма удивлён. Я вот как-то так поправил ваш код. Теперь "экстренная связь" с устройством будет даже в случае проблем.
Я сам этот код лично ещё не проверил - проверю, удалю этот дисклеймер.
Код:
import gc, webrepl, esp, network, json, os, time

# config.json example
# {
#     "wlan": {"ssid": "XXX", "password": "XXX"},
#     "webrepl": {"port": "III", "password": "XXX"}
# }

def init():
    try:
        with open('config.json', 'r') as fd:
            cfg = json.load(fd)
    except (OSError, ValueError):
        return webrepl.start()

    webrepl_config = cfg.get('webrepl', {})
    webrepl.start(**webrepl_config)
    if 'wlan' in cfg:
        sta = network.WLAN(network.STA_IF)
        sta.active(True)
        sta.connect(cfg['wlan']['ssid'], cfg['wlan']['password'])
        while not sta.isconnected():
            time.sleep(0.1)
        webrepl.stop()
        ap = network.WLAN(network.AP_IF)
        ap.active(False)
        webrepl.start(**webrepl_config)

    if 'main.py' in os.listdir():
        main = __import__('main')
        lst = dir(main)
        if 'init' in lst:
            main.init()

esp.osdebug(None)
init()
gc.collect()
размечтался.
попробуй,
удали.
 

__ab__

New member
Теперь "экстренная связь" с устройством будет даже в случае проблем.
Совершенно не обязательно - ведь:
1) в любом параметре можно ошибиться.
2) на ESP32 это работать не будет, т.к. в отличие от 8266 она не запоминает имени и пароля точки доступа, соответственно инициализация webrepl не сработает до кода:
Код:
if 'wlan' in cfg:
        sta = network.WLAN(network.STA_IF)
.....
И я бы не стал очень сильно увлекаться дурако-устойчивостью : любые вычисления требуют ресурсов, в том числе и обеспечивающие устойчивость. На устройстве, в ресурсах ограниченном, лучше лишнего не писать...

Да и вот это вот не очень код:
Код:
    webrepl.start(**webrepl_config)
    if 'wlan' in cfg:
        sta = network.WLAN(network.STA_IF)
       .....
        webrepl.start(**webrepl_config) # зачем ?
Кстати, webrepl и так неплохо инциализируется из своего конфига, так что я, в плане webrepl, не стал бы что-то менять в и так неплохо работающем коде ;)
 

nikolz

Well-known member
Совершенно не обязательно - ведь:
1) в любом параметре можно ошибиться.
2) на ESP32 это работать не будет, т.к. в отличие от 8266 она не запоминает имени и пароля точки доступа, соответственно инициализация webrepl не сработает до кода:
Код:
if 'wlan' in cfg:
        sta = network.WLAN(network.STA_IF)
.....
И я бы не стал очень сильно увлекаться дурако-устойчивостью : любые вычисления требуют ресурсов, в том числе и обеспечивающие устойчивость. На устройстве, в ресурсах ограниченном, лучше лишнего не писать...

Да и вот это вот не очень код:
Код:
    webrepl.start(**webrepl_config)
    if 'wlan' in cfg:
        sta = network.WLAN(network.STA_IF)
       .....
        webrepl.start(**webrepl_config) # зачем ?
Кстати, webrepl и так неплохо инциализируется из своего конфига, так что я, в плане webrepl, не стал бы что-то менять в и так неплохо работающем коде ;)
что мешает на ESP32 запомнить имя и пароль точки доступа?
 

nikolz

Well-known member
Прошивки micropython несколько разные на 32 и 8266 - одна сохраняет, а другая - нет.
При этом смысла лезть в прошивку и править её нет - всё легко решается кодом на python.
вы что-то путаетесь в терминологии.
код на питоне превращается компилятором и линкером в кусок прошивки.
 

__ab__

New member
вы что-то путаетесь в терминологии.
Как то неожиданно, что IT "гуру" может не знать, что такое интерпретатор...
Python как раз яркий представитель интерпретаторов - транслирует программу в p-код, который и интерпретирует..

Прошивка в данном случае это и есть интерпретатор. Текстовый файл .py транслируется в байткод и выполняется
Собственно вот C-код micropython, где видно как оно работает (выполняется байт-код)..
При желании, там же, рядом, не сложно найти как оно транслируется...

Больше читайте ;)
 

nikolz

Well-known member
Как то неожиданно, что IT "гуру" может не знать, что такое интерпретатор...
Python как раз яркий представитель интерпретаторов - транслирует программу в p-код, который и интерпретирует..

Прошивка в данном случае это и есть интерпретатор. Текстовый файл .py транслируется в байткод и выполняется
Собственно вот C-код micropython, где видно как оно работает (выполняется байт-код)..
При желании, там же, рядом, не сложно найти как оно транслируется...

Больше читайте ;)
ну да хамство вас не украшает.
не хотел читать ликбез.
но придется
питон как и луа и джава имеют VM
VM это не интерпретатор
интерпретатор работает со строкой вашей программы на конкретном языке и разбирает строку в реальном времени
VM машина работает с кодами ее собственных команд, как и любой железный процессор.
--------------
Но в ESP и OC и библиотеки и программа юзера помещаются во флеш в виде прошивки.
Поэтому даже если вы напишите что-то для интерпретатора, то и интерпретатор и ваш текст станут частью прошивки.
 

__ab__

New member
ну да хамство вас не украшает.
Оно никого не украшет, и Вас тоже ;)
Вы уж простите, если что, но видно что вы не очень знаете питон, то как он устроен и работает, но при этом пытаетесь что-то советовать.
Зачем? Сбивать с толку новичков, которых тут полно и самоутверждаться на них?
Судя по количеству симпатий в профиле, Вы многое знаете, но знать всё - невозможно. В этом нет ничего страшного :)

Про луа не скажу - не близок он мне и не ковырялся я в нем. Ни как профи, ни для хобби.
А что до Java и Python, есть разные реализации, которые немного по разному работают (особенно для Python)
В классическом варианте оба эти инструмента транслируют строки кода в байт-код, который потом интерпретируется (ссылку на интерпретирующий код код я давал). В случае Java - транслятор это javac и машина это java. В случае питона все происходит внутри одной программы, причем эта программа умеет еще и на лету транслировать строки в байт код и передавать интерпретатору байт-кода (repl).
Для того чтобы работать быстрее, питон умеет создавать претранслированные файлы байт-кода (но это не код процессора, в отличие от объектнгого кода, который генерит компилятор!)
Кроме того, python (с первых версий) изначально отличался тем, что его интерпретатор легко встроит в код для C компилятора (изначально), а так же в сам питон легко встраивать библиотеки, написанные на С, при этом такие библиотеки выглядят, как написанные на питоне (пример: psycopg2)
Пишу "изначально", потому подойдет любой код, который сможет слинковать Python (ASM, pascal...)
Но не надо путать C библиотеки с библиотеками которые написаны на питоне.
Первые встроены в firmware (раз не нравится "прошивка"), вторые генерируются динамически.
 
  • Like
Реакции: fps

BigStupidBeast

New member
Для тех кто будет читать это в 2020м.
main.py стартует самостоятельно.
версия прошивки esp32-idf3-20191220-v1.12
если вставить кусок кода из примера выше

Python:
import os
lst = os.listdir()

if 'main.py' in os.listdir():
    main = __import__('main')
    lst = dir(main)
    if 'init' in lst:
        main.init()
то программа запустится дважды.

Python:
import main
эффект тот же

(для запуска рекомендую использовать Thonny. ESPlorer криво залил мне на ESP32 файлы, а Mu не видит что лежит на ESP32. )
 
Сверху Снизу