Need general guidance on how to run scripts

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
liudr
Posts: 211
Joined: Tue Oct 17, 2017 5:18 am

Need general guidance on how to run scripts

Post by liudr » Sun Apr 08, 2018 1:52 am

I know the following about MicroPython:
  • boot.py runs at boot
  • main.py runs next
  • System enters serial REPL after main.py exits.
  • All variables defined in main.py remains in scope in serial REPL, which is really nice.
Now what I envision is a custom script, say Logger.py, that runs after main.py and shares the same name space as main.py so all the imports and variables are passed to logger.py.

So my question is : How do I run Logger.py?
  • Automatically on start-up (once I complete the development I want the code to run on boot)
  • Manually once I am in serial REPL (while I'm still doing development I want this option to probe around inside serial REPL)
I tried from Logger import * but the imported Logger doesn't see the variables defined in main such as an rtc variable. Once it throws an exception and I'm back in serial REPL, I can access rtc just fine.

Thanks.

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: Need general guidance on how to run scripts

Post by OutoftheBOTS_ » Sun Apr 08, 2018 2:28 am

Automatically on start-up
just add to the end of main.py

Code: Select all

import Logger
Manually once I am in serial REPL
just type in to the repl

Code: Select all

import Logger
Do beware that you can only import once so if you want to rerun the script for a second time you have to first remove it then import it again. I have added reload() to my boot.py for this so that the second time I want to rerun the code I will type reload(Logger)

Code: Select all

# This file is executed on every boot (including wake-boot from deepsleep)
import sys
sys.path[1] = '/flash/lib'

import gc
from sys import modules
def reload(mod):
  mod_name = mod.__name__
  del sys.modules[mod_name]
  gc.collect()
  return __import__(mod_name)

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Need general guidance on how to run scripts

Post by pythoncoder » Sun Apr 08, 2018 7:28 am

liudr wrote:
Sun Apr 08, 2018 1:52 am
...
I tried from Logger import * but the imported Logger doesn't see the variables defined in main such as an rtc variable. Once it throws an exception and I'm back in serial REPL, I can access rtc just fine...
Python doesn't work like that. Create a file foo.py with

Code: Select all

print(a)
Then, at the REPL, do the following

Code: Select all

>>> a = 22
>>> import foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/adminpete/foo.py", line 1, in <module>
    print(a)
NameError: name 'a' is not defined
>>> 
You will see the same in MicroPython and in standard Python. A module has its own namespace and does not inherit the namespace of the calling scope. Nor does it export its names to the caller (MicroPython's main.py and boot.py notwithstanding).

This separation of namespaces is actually a great feature saving a lot of potential bugs. It's usually bad practice to issue

Code: Select all

from module import *
precisely because it corrupts the namespace of the calling scope. I once encountered a nasty bug where a vendor module imported in that way had redefined a standard Python function wrecking my calling program.
Peter Hinch
Index to my micropython libraries.

User avatar
liudr
Posts: 211
Joined: Tue Oct 17, 2017 5:18 am

Re: Need general guidance on how to run scripts

Post by liudr » Mon Apr 09, 2018 4:00 am

Thanks guys. For now, I copy and paste the entire data logger script in main.py. This way there is only one namespace. What if I do need to send some variables to an imported module? How do I go about doing that?

I'm still learning python. The import process is not present in C/C++. I'm used to #include with header files. So you use import to load function definitions, primarily, correct?

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: Need general guidance on how to run scripts

Post by OutoftheBOTS_ » Mon Apr 09, 2018 10:24 am

I have only been programming in python for a year now so am still learning a lot.

Not sure if my answer is 100% correct so if I get anything wrong someone will need to correct me.

For me import feels like a cut and paste from the file you have imported from. If you have a file called Logger.py and you use import Logger then it cuts and pastes the contents of Logger.py. If you use from Logger import my_function then it will cut and paste the function called my_function from the file Logger.py. If you type from Logger import my_class then it will cut and paste the class(object) called my_class from the file Logger.py.

Once you have imported the function or class then you can pass arguments to it e.g my_function(arguments)

Once you import a class(object) then you can create and instance of it and pass arguments to it e.g my_pointer = my_class(init_arguments)

Hopefully I am at least part right with my answer :)

So for your Logger code you can turn it into a class and use it something like this

Code: Select all

from Logger import logger_class

my_logger = logger_class(init_argumanets)

#if you want to interact with a fuction in the logger_class you can do it like this
#my_logger.my_fuction(arguments)

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Need general guidance on how to run scripts

Post by dhylands » Mon Apr 09, 2018 5:24 pm

It doesn't actually cut/paste.

Then you say import Logger, the the interpreter will find Logger.py and execute that code. A reference to the Logger module will be saved.

When you say from Logger import my_function, then it will find Logger.py and execute that code. It will then setup an alias for my_function such that you can refer to my_function rather than Logger.my_function.

The memory usage in either case seems to be identical. I created a Logger.py:

Code: Select all

def my_function():
  print('my_function')

def other_function():
  print('other_function1')

def other_function2():
  print('other_function3')

def other_function3():
  print('other_function3')

def other_function4():
  print('other_function4')

def other_function5():
  print('other_function5')

def other_function6():
  print('other_function6')

def other_function7():
  print('other_function7')

def other_function8():
  print('other_function9')

def other_function9():
  print('other_function9')
and then created t1.py:

Code: Select all

import Logger
Logger.my_function()
import gc
gc.collect()
print('mem_free =', gc.mem_free())
and t2.py:

Code: Select all

from Logger import my_function
my_function()
import gc
gc.collect()
print('mem_free =', gc.mem_free())
Running t1.py or t2.py in the unix version of micropython produced identical results:

Code: Select all

my_function
mem_free = 2069408

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Need general guidance on how to run scripts

Post by pythoncoder » Mon Apr 09, 2018 6:24 pm

It's also worth thinking about namespaces. If you issue

Code: Select all

import pyb
you can access objects (functions, classes, data objects) in the module with code like

Code: Select all

my_adc = pyb.ADC(1)
The names defined in pyb can never clash with names you've defined because they have to be prepended with pyb.. There is a case for using this exclusively.

If you issue

Code: Select all

from pyb import ADC
you have imported the specific name ADC into the namespace of your code. If you've defined an object of your own called ADC there will be a clash and the last definition will take precedence. The same will occur if you import the same name from more than one module.

Lastly there is

Code: Select all

from pyb import *
This will bring every item defined in the module into your namespace. This can be hazardous unless you know exactly what names the module defines. Use only when you are sure what names the module defines.
Peter Hinch
Index to my micropython libraries.

User avatar
liudr
Posts: 211
Joined: Tue Oct 17, 2017 5:18 am

Re: Need general guidance on how to run scripts

Post by liudr » Tue Apr 10, 2018 5:36 am

Great. Thanks. I know now that there is no memory benefit in importing just one module, such as Pin from machine. I'll just import machine and use machine.Pin. I didn't know the code runs regardless how you import the module.

Post Reply