174 Pi: Creating Python Packages of Functions (174.html)

NOTE: this includes my first Thonny Package of Importable Functions

Keywords:
ICH180R2 "Raspberry Pi" Raspberry Pi Python Thonny Packages D@CC "Raspberry Pi Thonny" show show2 printsho from import PiR2 KY-18 ADS1115 adc redLED photo-cell ambLight digLight isTypeStr shebang hashbang n.py IX_textpack.py IX_textpack_pkg IX_textpack_pkg.py adcRead_pkg adcRead adcRead_test.py textpack.py "./" "./n.py" "#! " "#! /" "#! /usr/bin/python3" "#!/usr/bin/python" stdin stdout pipe piping Dunder Underscore "__" "_" cmdLoop "command list" "standard executable program" ixv_




Click on the photo to enlarge it.

thumb: IMG_5180.JPG

US$15 Raspberry Pi Zero 2W in a case

This inexpensive computer can access the web via wifi, use email, run Python programs
headlessly, access bluetooth devices and use electronics e.g. to blink an LED.

Introduction

When developing software, it is sometimes convenient to store a group of functions (or subroutines) in an external library. Any or all of the functions can be imported from this external library. This reduces the volume of code that must be included in an application. If this library is stored outside of the computer, i.e. somewhere on the web, then it is simply imported by mentioning the name of the library in the application and the word "import" with special syntax. This same process can be done if the library is stored on the same computer as the application. Normal Python provides a way to do this, but Thonny does it a different way. The purpose of this article is to describe how I created and used my first such external Thonny library. Such a library is called a package. The more complex packages permit the definition and creation of classes, objects, methods, functions, and the modules pertaining to the objects. Such a module can be used in an identical manner to a normal function (which is not a object module.) At first, these packages seem to be complex with many strange rules about how they are defined. Hopefully, this article clarifies some of this.

Development Environment

This article explains how I successfully created the function show(str1,int3) which is stored in package piIX01. It is a function of the object named Raspberry. This development work was performed on my Pi400 using a micro SDcard with id Fla75S032G using Raspberry OS version buster. The development work was all initially done in folder PiIX01 which is stored in the Desktop folder. I experimented with different ideas and eventually finished in folder PiIX07.

The naming conventions, storage locations and syntax are especially important for a Thonny package to operate correctly and to permit development of future versions of the application program that calls the function(s) in the package. Within the piIX07 folder (but OUTSIDE a python IX package) for Thonny, at least the following 3 files must exist:
__init__.py       (package definer)
Raspberry.py      (where the show() function is defined)
afTest07.py       (a program which calls the show() function
The files __init__.py and Raspberry.py must be editted here in this folder but they must also be uploaded to the Thonny package folder called PiIX07 before they are usable. (These modules can also be stored in an IX package as a backup copy, but this copy would be a third copy of the exact same modules. Unfortunately Thonny packages require more work on the part of the programmer than the python3 IX packages.)

As a temporary sidenote . . . . it turns out that when a programmer uses both Thonny and Python3 versions of a package named "IX_08_pkg" in a Sandbox folder, all the following superfluous copies of the same modules become necessary:

	  /home/pi/Sandbox/__init__.py   the module by whose presence Thonny detects this to be a package folder 
	  /home/pi/Sandbox/afTest08.py   the main test module that uses (calls) the modules in IX_08_pkg.py
	* /home/pi/Sandbox/IX_08_pkg.py  a copy of each function in the IX_08_pkg package for initial editing by the programmer
	                                  [This copy can be used for initial editting and module testing by the programmer.]
	                                  [It is believed (but not known for certain) that functions outside of a class definition are permitted by Thonny]
	* Thonny/IX_08_pkg.py            a copy of each function in the IX_08_pkg.py package for use only by Thonny
	* /home/pi/Sandbox/IX_08_pkg.py  a copy of each function in the IX_08_pkg package for python3 to make a copy named *.pyc
	* /home/pi/Sandbox/IX_08_pkg.bu  a copy of each function in the IX_08_pkg package to serve as a backup
	* /home/pi/Sandbox/IX_08_pkg.pyc a copy of each function in the IX_08_pkg package for use only by python3
	
From the point of view of the programmer, all five copies of the modules (marked by an "*" above) in the package named IX_08_pkg should (at least initially) be identical. If more than one function (module) exists in the package named IX_08_pkg, it should be included in every module marked above with an asterisk ("*"). During the initial development and testing of each function, for ease of testing, the function will probably also exist as a separate python source file in the Sandbox folder. But once the function has been satisfactorily tested, it must be moved (or copied) into the 5 packages marked with an "*". The author apologizes for the complexity of these copies. But this is the situation because the developers of Python3 (for RPi and many other computers) and Thonny (for RPi and Pico) do not yet agree on their package definitions and mechanisms.


Returning to the minimal Thonny package definition PiIX07, the Raspberry.py file will house the Thonny show() function. The file afTest07.py is the Thonny application that calls show(). It must keep its same name unchanged but can be editted in this folder (but not anywhere else). Using the correct "import" syntax, the program afTest07.py can call any of the functions or modules in the PiIX07 package.

Package Specifier: __init__.py

This file defines the Thonny folder housing it to be a package. Some Python packages permit this file to be empty, but for a Thonny package, it must contain a line defining each object in the package. In our example it must contain:
from Raspberry import Raspberry

Object Definition: Raspberry.py

This file defines a class of objects in the PiIX07 package. An object can contain a number of sub-objects, called models in this case. But these sub-objects are of little importance at this time. As can be seen, the Thonny function called show() is also defined. It is defined as a method of the object Raspberry and must be referred to as such. Such a method can be called using the format "object.show(str1,int2)". The first argument "self" is a reference to the object for which the method is defined. As seen below, the simple function show() simply prints out the arguments and doesn't return anything more complex.
#Raspberry.py in piIX07 on 2022BFeb28 by D@CC
# Python code to illustrate the Module
class Raspberry:
    # First we create a constructor for this class
    # and add members to it, here: models
    def __init__(self):
        self.models = ['Pi', 'Pico', 'Generic', 'Other']
    #def end
    # A normal print function
    def outModels(self):
        print('These are the available models for Raspberry:')
        for model in self.models:
            print('\t%s ' % model)    # the "\t" defines the format to use
	#for end
    #def end
    def show(self,str1,int2):
        #arg1 of self doesn't count as a "calling argument"
        print('str1:',str1,'int2:',int2)
        print('\t %s  %d' % (str1 , int2) )
        print('returning "xyz"')
        print('end of show.py')
        return "xyz"
    #def end
#class end

Application Definition: afTest07.py

#afTest07.py in Desktop/PiIX03/
# on 2022BFeb28 by D@CC
# my first working import of one of my Thonny packages
# Import classes from your brand new package
# Package folder PiIX07 contains 2 files: __init__.py and Raspberry.py
from PiIX07 import Raspberry
   
# Create an object of Raspberry class & call its method
IX = Raspberry()
print("I created an object named IX")
print("I am not yet using the 4 models")
IX.outModels()
isP=1
abcd="a123b"
# invoke the show function for this object
# resultStr=IX.show("abcd",isP)
resultStr=IX.show("abcd",isP)
resultStr=IX.show("efgh",isP)
print(resultStr)

#from Cars.Audi.a8 import get_buy

print("exit afTest07.py")

#prerequisites in Thonny Package Library
# folder IX
#         __init__.py
#         Raspberry.py
# Source: 1: http://geeksforgeeks.org/create-access-python-package
# Title:    Create and Access a Python Package
# By:       Chinmoy Lenka  On 15 Feb, 2018
# Source  1 does not work for Thonny packages
# Source  2 works for Thonny packages
# Source: 2: https://www.tutorialspoint.com/create-and-access-a-python-package
# ThonnyPackageLibrary: /home/pi/.local/lib/python3.7/site-packages
# To view Library a)thonny b)Tools c)Target: user site packages
#Documentation: /home/pi/Desktop/PythonPackageCreation.txt
# Note 3: I will develop afTest.py in Desktop/PiIX07/
#         the package will be PiIX07 containing show2.py and outModels
#         their references will be IX.show and IX.outModels
#         One object will be created named IX of class Raspberry
#         This program, /Desktop/PiIX07/afTest07.py, will be used for testing
# Note 4 The names of the app folder and the package folder match.
#        See PythonPackagesNotes.txt
#        also changed the name of this app.
# Note 5 I discovered that I could not use the editor while
#        Tools-Package was open.  I needed to edit the package
#        routines elsewhere. I also discovered that it is not
#        the folder of the app that is "married" to the package.
#        It seems that the name of the app (or the contents of
#        the app) were "married" to the package.  So I changed
#        the name of the app to "force" a new marriage of the
#        app to the revised package.  I wonder if it was really
#        necessary to change the name of the package, but I
#        did, just to be safe.  It then worked with the newly
#        editted package.   Sweet success at last!
#        I was able to edit the app and run it again using the
#        package. Note that I did not change the name of the app itself.
#end of afTest07.py

Eventual Usage of Application afTest07.py

Once the package PiIX07 has been completely defined, the application can be run under Thonny. Note that all of the statements beginning with a "#" are comments; the actual code is very short. When run, it will produce the following output:
I created an object named IX
I am not yet using the 4 models
    "abcd"   1
    "abcd"   1
returning xyz
   1
exit afTest07.py
Note that the following import statement caused the function "show" to be imported as part of the object type Raspberry:
from PiIX03 import Raspberry
This had the effect of "inserting" the code for show() as if it were actually part of the code of afTest03.py. This is exactly what we needed the package to do. The next section explains how to create the Thonny package.

Creating the PiIX03 Thonny package

In order for the "import . . ." statement to work, Thonny must be informed that the package PiIX03 exists. The latest version of the PiIX07 package can be found in Source 3 below. This package can be implemented in Thonny in the following steps:

Python Package Creation Example
On 2022BFeb27 by David4ColeCanada@gmail.com

1. Create a directory and name it Cars
   [all the following modules will be placed in this dir.]

2. Then create the first 3 modules.  
   [Create the file named Bmw.py]

#Bmw.py in Cars
# Python code to illustrate the Modules
class Bmw:
    # First we create a constructor for this class
    # and add members to it, here models
    def __init__(self):
        self.models = ['i8', 'x1', 'x5', 'x6']
    #def end
    # A normal print function
    def outModels(self):
        print('These are the available models for BMW')
        for model in self.models:
            print('\t%s ' % model)
	#for end
    #def end
#class end

#Audi.py in Cars
# Python code to illustrate the Module
class Audi:
    # First we create a constructor for this class
    # and add members to it, here models
    def __init__(self):
        self.models = ['q7', 'a6', 'a8', 'a3']
    #def end
    # A normal print function
    def outModels(self):
        print('These are the available models for Audi')
        for model in self.models:
            print('\t%s ' % model)
	#for end
    #def end
    def outModel_a8(self):
        print('These are the available a8 models for Audi')
        for model in self.models:
            if model=='a8':
                print('\t%s ' % model )
            #if end
	#for end
    #def end

#class end

#Nissan.py in Cars
# Python code to illustrate the Module
class Nissan:
    # First we create a constructor for this class
    # and add members to it, here models
    def __init__(self):
        self.models = ['altima', '370z', 'cube', 'rogue']
    #def end
    # A normal print function
    def outModels(self):
        print('These are the available models for Nissan')
        for model in self.models:
            print('\t%s ' % model)
	#for end
    #def end
#class end

#__init__.py in Cars (can be empty)
from Bmw import Bmw
from Audi import Audi
from Nissan import Nissan


#sample.py
# Import classes from your brand new package
from Cars import Bmw
from Cars import Audi
from Cars import Nissan
   
# Create an object of Bmw class & call its method
ModBMW = Bmw()
ModBMW.outModels()
   
# Create an object of Audi class & call its method
ModAudi = Audi()
ModAudi.outModels()
  
# Create an object of Nissan class & call its method
ModNissan = Nissan()
ModNissan.outModels()


#getbuyProgram.py
#from Cars.Audi.a8 import get_buy

#Now call the function from anywhere:
get_buy(1)   #this method has not been (but must be) defined

print("end of getbuyProgram.py")
#end of getbuyProgram.py

Source: Thonny Packages




Title: This worked for Thonny 
  as of 2022BFeb23
  I am still modifying it replacing Cars with IX
Thonny uses its own virtual environment by default. Open 
"Tools => Manage packages" or "Tools => Open system 
shell" in order to install into this environment. For 
completeness I will add that once you are in the 
Thonny System Shell you can run either "pip" or "pip3" 
to install the module you need.
1. Tell Thonny to include the Tools menu
2. Restart Thonny, then click on "Tools"
3. Select "Manage Packages"
4. Read "Target: user site packages
     from /home/pi/.local/lib/python3.7/site-packages
   This dialog lists all available packages, but allows 
   upgrading and uninstalling only packages from 
   /home/pi/.local/lib/python3.7/site-packages . 
   New packages will be also installed into this 
   directory. Other locations must be managed by 
   alternative means.


Source: https://www.youtube.com/watch?v=Oo-B98WWre8
Title: Thonny: The Beginner-Friendly Python Editor
By Krishelle hardson-Hurley


Source: http://geeksforgeeks.org/create-access-python-package
Title: Create and Access a Python Package
By Chinmoy Lenka  On 15 Feb, 2018
NB This doesn't work for Thonny

/PythonPackageCreation.txt
Other resources pertaining to PiIX07 are in the zip file in Source 3. These txt files are:
HowToManageThonnyPackage.txt
PythonPackageCreation.txt
PythonPackagesNotes.txt

Well-Defined Python Functions

I believe that a "well-defined" Python function should include the following information:

Name:
Arguments (passed):
Author (if known):
Classes (defined for use):
Command List (if prg):
Date (written):
External Functions called:
Files Used:
Globals (for ext. use):
Globals (int. use only):
Help (or Manual):
Import From Pkg.:
Imports Pkg. Used:
Prerequisite (Object/Function):
Python Verson: 2, 3, Thonny
Result (return/yield):
Version (latest):

Use of Globals in Python

Global variables can be of great importance when programming. Simple software systems do not need Global variables. But when subroutines and functions begin to bloat the main application program, they are moved into a package that can be imported. But these imported functions and subroutines often need to be passed many variables. When the number of passed variables becomes problematic, the "~40 year old" concept of COMMON variables is needed. In Python, such common variables are called global variables. The best approach is for all the global variables to be placed (defined and used) in the main package housing the subroutines, functions and methods. When the main program needs to access subroutines and functions, it in usually accomplished with a statement that imports the package (such as shown below:
    import pir2A
    import pir2Data
When a function [e.g. isTypeStr() ] or subroutine in the package is referenced, the reference is preceded by the name of the package as shown below:
    if pir2A.isTypeStr(targTempL0) :  
        . .  statements. . . 
    #if end
The actual isTypeStr() function is a little more complex, but no more will be said about it here.

It is a good programming practice to use a naming convention to identify global variables. For this I almost always use "g_" as the first 2 characters of every global variable. One caveat for global variables is that the global variable must be declared in the subroutine/functions using it. Furthermore, the global variable must be first referenced in the subroutine/function where the global variable will be stored. This means that the main application program must not reference, create or define a global variable first. But sometimes a global variable must be defined or used early in the main application program. An example of this is the SetPoint or Target temperature (eg g_targTempL0) in a control system. In the PiR2 system, during start-up of the system, the issue is "How do I reference "g_targTempL0 in the main application program.

My solution is to use a variable name without the "g_" prefix such as "targTempL0". My dialogue with the user makes use of the variable named "targTempL0". So, how do I initialize the global variable that is used in the subroutines? The statement below will not work because the global variable must be first used in the subroutine in the package.

   g_targTempL0 = targTempL0      # BAD CODE
I have written a pair of subroutines (named set... and get...) to resolve this issue. The preferred statement (to replace the above bad code) is:

     pir2.set_global("g_targTempL0", targTempL0)     # GOOD CODE
    . . . .
     targTempL0 = pir2A.get_global("g_targTempL0")   # GOOD CODE
The second statement shown above can be used later to dynamically retrieve the global value. In fact, both statements operate dynamically making use of the current value of the global variable. This process needs these global variables to be declared in the pir2A.access_global() subroutine. Not all global variables need to be declared in this fashion, only those that need to be dealt with in the main application routine. Using these routines (statements) has facilitated my use of Python global variables.

The isTypeStr() function

I found it to be slightly awkward to test if a variable is a string. Sometimes, one of my programs asks a user to input a variable such as Age into a variable called ageStr. But, in Python2, the user might enter "18.5" or " 18" or "18". It would be recognized as a string only if the user preceded the digits by a space. The program needs to distinguish between string and numbers. Python3 addresses this issue. My solution is to convert everything into a string or a number as shown below:

    input (ageStr)
    if isTypeStr(ageStr) :
       . . . 
    else :
       . . .
    #if end

Definitions of Globals and isTypeStr() Functions

Source 04 contains an up-to-date version of these functions. The global functions and the isTypeStr function are listed below:

def access_global_list_definition():
    #by D@CC
    # This must be defined in the pir2A.py module (not the calling program)
    # it should be called ONCE during main program initialization
    # But it can be called from anywhere using
    # pir2A.access_global_list_definition()
    global gAL
    gAL=""
    gAL=gAL+"."+"g_targTempL0" ; global g_targTempL0
    gAL=gAL+"."+"g_gALtest"    ; global g_gALtest
    nCount=2
    returnValue = "globalAList was defined containing a global Count of : ",nCount
    #print("gAL:"+gAL)
    return returnValue
#def end

def access_global(gName,AorR,value):
    #by D@CC
    # This must be defined in the pir2A.py
    # It doesn't need to be called from outside the pir2A.py
    # check if in the gAL (globalAccessList)
    global gAL
    gAL1=""
    gAL1=gAL1+"."+"g_targTempL0" ; global g_targTempL0
    gAL1=gAL1+"."+"g_gALtest"    ; global g_gALtest
    # all globabls used here must be pre-defined here in this list,
    # but their values need not be pre-defined
    # With some additional work, this will be only
    #                    done in access_global_list_definition()
    nCount=2
    #print("in access_global,gAL:"+gAL)
    #print("gAL:"+gAL)
    #print("found:", gAL.find(".") )
    #print("found:"+gName,gAL.find(gName))
    if gAL.find(gName)==-1 :
        #print("didn't find:"+gName)
        print("ERROR global Name cannot be accessed:"+gName)
        returnValue = gName+" ERROR: is not in the globalAccessList!"
    else:
        # match/case don't work yet in Python
        if gName == "g_gALtest":
                if AorR == "Assign": g_gALtest    = value
                else: returnValue  = g_gALtest
        if gName =="g_targTempL0":
                if AorR == "Assign": g_targTempL0 = value
                else: returnValue  = g_targTempL0
        #if end
        if AorR=="Assign" :
            if isTypeStr(value):
                returnValue=gName+" was assigned value:"+value+":"
            else:
                returnValue=gName+" was assigned value:"+str(value)+":"
            #if end
        else:
            continueDoh=1
        #if end
    #if end
    return returnValue
#def end

def get_global(gName):
    #by D@CC
    global gAL
    #print("in get_global,gAL:"+gAL)
    #this is usually called from outside the pir2A.py
    # it can be called e.g. gALtest = pir2A.get_global("g_gALtest")
    return access_global(gName,"Retrieve","na")
#def end

def set_global(gName,value):
    #by D@CC
    #print("in set_global, gName:"+gName)
    #this is usually called from outside the pir2A.py
    # it can be called e.g. pir2A.set_global("g_gALtest",value)
    # WARNING: it will over-ride the current value of this global value
    access_global(gName,"Assign",value)
    if isTypeStr(value):  returnValue= gName+" was set="+value
    else:                 returnValue= gName+" was set="+str(value)
    #doesn't work if value is not a string
    return returnValue
#def end

def get_targTempL0(str1):
    returnValue = access_global("g_targTempL0","Retrieve","na")
    return returnValue
#def end

def isTypeStr(vName):
    # there is a better version of this somewhere on my computer
    Ttype=type(vName)
    if Ttype=="": return True
    else: return False
#def end
#/global_and_isTypeStr.py

Comprehensive List of My Python IX Functions

Source 05 is the latest most comprehensive list of Python functions developed by the author. This text file lists the functions and their test programs in a text file named "IX_Python_Functions.txt". It also provides a link to a repository where the source code of each function and program can be found. The Source Code for the 3 functions listed below was not readily found. But the author has recently discovered where each of the 3 were encountered or defined.

isInstance() standard python function: used in f3() in my Article 155)
mid()        used in f3() & IX vector functions (in my Article 164)
mid()        using in MySQL
mid$()       used in PicoMite MMBASIC
pack()       defined in Tkinter, the GUI package
pack()       defined in textpack by O'Reilly (Source 08)

Source 02 includes my first reference to the unique Unix Executable Scripts ("ExecutableScriptsOnUnix.txt"). The latter describes how a text file can become a "standard" executable Python program in a Unix (or Linux) system. A "standard" executable program is a program that uses std input and a std output, often with a string of command list letters. These "standard" programs can be used with "piping" in Linux command lines. These standard programs are usually written in "C" but it is possible to use python programs in this manner using the "./" prefix. The "./" prefix is sometimes called a "shebang" or "hashbang" prefix. The author has created such a Python program called "n.py" that can function as a "standard" linux program in piping situations.

IX "textpack" Program Package for Python (Not Thonny)

The IX_textpack.py and IX_textunpack.py routines can be used to group (or ungroup) many functions (or subroutines or programs) in one text file. The resulting file can be easily copied (or downloaded) to a new location (or a new computer). The original author of the textpack concept (O'Reilly in Source 08) suggests that the following marker be used to separate the files in the text package:

::::::::::textpak=>

THis marker is immediately followed by the name of the file that follows it. But there is nothing wrong with putting a "#" in front of the marker. By doing this, the record preceding the python printSho.py function definition would be as follows:

#::::::::::textpak=>printSho.py

By doing this, the marker is considered as a comment line if the files are python files instead of non-python text files. This has the added advantage that the resulting package (i.e. big file) is seen to be just a group of python function definitions concatenated together. A group of python functions concatenated together is exactly what python-3 (but not Thonny) considers to be a python package. By doing this, any python program can simply use an import statement to make use of any function in the package. For python3 the package must be placed in the same directory as the program calling the function. For example, the printSho() function can be imported and used by the "printSho_test.py" program as follows:

from  IX_package_py import printSho

progName="printSho_test.py"
printSho()
print("end of "+progName)
#end printSho_test.py
For python3, it is not even necessary to precede the printSho() by the package name. Furthermore it is not necessary to use the IX_textunpack.py routine to unpack the package. Of course, if desired, the functions can be unpacked and placed in different folders or included in the calling programs. I normally place the test programs and the package in a folder named IX (that is located in the Desktop folder.) To facilitate packing and unpacking, I place the IX_textpack.py and IX_textunpack.py programs in the Desktop folder. Usually, I also prefix "IX_" in front of the names of my versions of the textpack and textunpack program names. Do not be surprised to notice that, when using the package, Python makes a (modfified) copy of the package with an extension of ".pyc" .

WARNING: Do not make any changes to a file with an extension of ".pyc"!

The following command line, when typed into Terminal, will pack the given list of files:

$> python ..\IX_textpack.py spam.txt eggs.txt ham.txt > packed.all
When using this syntax, the IX_textpack.py routine must be located in the folder above the files.

My First Complete Python Package: IX_textpack_pkg.py

I have created a package containing 7 Python programs and a help file. They are:

IX_textpack.py      packs a list of files into a package
IX_textunpack.py    unpacks ALL the files from an existing package
IX_textselect.py    selects (unpacks) a SINGLE file from an existing package
IX_textpack.txt     explains HOW to use IX_textpackPkg_py.txt
IX_textnames.py     lists the filenamess in a package (deprecated . . . use  n.py]
IX_textadd.py       adds a file to the package (deprecated. . . use IX_textpack.py with ">>" instead)
n.py                lists the various contents of the package
This complete package is merely the big text file seen in Source 10.

The first 3 Python programs are all that is needed to create and use a package that is usable as a Python library by Python3. (For this purpose, the package must have an extension of ".py".) But to make is easy to download from the web, its extension is ".txt". Normally a group of functions or programs are loaded into a program library. But larger program systems often need a group of functions that are specific to that system. An IX_textpack package can also hold the functions specific to a single program system. Many programs are often written to test various related concepts. Such a group of programs can clutter up a folder. However, rather than deleting these programs, they can be put into a test package. Later, if one of these programs needs to be revisited, it can be selectively unpacked from the the test package. For example, the help file named IX_textpack.txt can be selectively unpacked from IX_textpack_pkg.py .

To view the file names in any IX package (e.g. IX_textpack_pkg.py), simply use the following command in Terminal:

>$ python3 n.py < IX_textpack_pkg.py
The current filenames in that package are:
	#Be sure to precede the Pkg name with a "<".
	IX_textunpack.py
	IX_textselect.py
	IX_textpack.txt
	IX_textpack.py
	IX_textadd.py
        n.py
        nShowDefs.py
	*** end of list by n.py
	
My thanks to O'Reilly (Source 08) for documenting this (or his) package concept.

Future Python Packages

Recently, I have reviewed my many excursions into the Python world. I have reviewed hundreds of Python programs, some that I wrote and many that I have discovered. I plan to group them together into various packages. My current thoughts are to create the following Python package groups:
Package Name                Contents
---------------------       ------------------------------------------------
* adcRead_pkg.py            python RPi functions for adc sensing of voltages (Source 11)
* adcRead_programs.py       python RPi programs for adc sensing (Source 16)
                              adcRead_test.py needs to import adcRead_pkg.py
* functionList_pkg.py       routine used by n.py to list the function names in a statement
  IX_DataSheets.Sources.txt Electronic DataSheet Sources (e.g. pdf.html) 
  IX_diagnostics_py.py      python diagnotics for Raspberry Pi Hardware
* GPIO_pkg.py               pir2 & GPIO functions (possible duplicates in other pkgs)
  IX_ICH180R2_A.php         php & html routines for the future ICH180R2 website
  IX_MIC.php                php & html routines for the MehInCharge website
* IX_MMBasic_pkg.bas        functions, subroutines and programs written in Basic
* IX_MMBasic_notes.txt      text files about MMBasic for PicoMite hardware
* IX_package_py.py          precursor to the IX_py.py package
  IX_pi_py.py               python functions for pi computers
  IX_pi_notes.txt           Miscellaneous notes about Pi computers
  IX_pi_sources.txt         My Sources of Pi Information
  IX_pico_py.py             python functions for pico computers
  IX_picoMite.bas           software written in basic for PicoMite hardware  
  IX_pir2.py                python functions for the PiR2 controller
  IX_pir2_info              pir2 information
  IX_pir2models.py          python functions for the various PiR2 controllers
  IX_projects_py.py         python software for various projects
  IX_py.py                  python functions common to pi&pico computers
  IX_python_info            python 2 & 3 language information
  IX_RPi_hardware.txt       Raspberry Pi Hardware Descriptions
* IX_testPrograms_py.py     various programs to test hardware and software
* IX_textpack_pkg.py        IX_text pack/unpack/select/etc & n programs (Source 10) 
                              deprecated replaced by IX_textpack_programs.py
* IX_textpack_programs.py   IX_text pack/unpack/select/etc & n.py programs (Source 17)
  IX_thonny_pkg.py          IX functions to become a thonny package
My current emphasis will be on the above packages marked by an asterisk. These packages are limited to source code and text documents. Some of these documents will contain ascii characters (e.g. Windows NoteBook txt documents) while others will contain Unicode characters (e.g. Raspberry MousePad txt documents). I plan to make use of the Consolas-10 monospaced font whenever possible. The creation of many of these package libraries will take a long time and is a project that will realistically never be complete. Other packages will evolve and will move through many development phases. I have begun to only use the suffix "_pkg" for package names that contain python functions (not programs). For this reason the set of textpack programs are now stored in "IX_textpack_programs.py" which is a package but contains no externally callable functions.

Python2 vs Python3

During my testing of this package, it was necessary to research some of the differences between Python2 and Python3 (See Source 09 for more details.)

Python Package adcRead_pkg.py to read from the adc chip ADS1115

Source 11 is the Python package that contains adcRead() and related functions that enable any of the 4 sensors to be read by the adc converter in IC chip ADS1115. SeeedStudios (Source 13) sells a board housing an RPi 40 pin connector, the ADS1115 ic, and the 6-terminal "screw" strip described below. Wires can be attached to the 6 terminals which are labelled:

(L-R) 3v3, AIN3, AIN2, AIN1, AIN0 and GND

WARNING: sensing voltages higher than 3v3 will harm the board.
WARNING: when sensing a voltage, a wire must also be connected to GND.
Click on the photo to enlarge it.

thumb: RPi_ADS1115_fullview.jpg


SeeedStudio Board RPi ADS1115 (upside-down)

Click on the photo to enlarge it.

thumb: RPi_ADS1115_fullviewInverted.jpg


SeeedStudio Board RPi ADS1115

Also visible in the above photo is a Grove connector possibly permitting other I2C modules to be used remotely. In fact, this Grove connector "asis" probably allows adc sensing of a remote voltage (at the end of the Grove cable on pin 1.) But the RPi uses (drives) Grove Connector pin 1 (originally I2C clock, which I believe is sensed by AIN0 of the ADS1115), this I2C signal will also be sensed on AIN0 by the ADS1115. So, to sense a signal on Pin 1 of the Grove connector cable, ensure that Pin 1 is NOT also internally connected to I2C clock from the RPi GPIO connector pins. I do not know whether or not Pin 2 of the Grove connector is truly NC or if it is connected to I2C serial data from the RPi GPIO connector pins. I have posted this question on the SeedStudio forum (Source 13).

Up to 4 similar boards can be easily connected together to sense up to 16 values. Source 12 contains a test program named "adcRead_test.py" that calls the adcRead() function. The program can be configured to read any 1 of the 4 sensors and can either read it once or continuously. Because the RPi cannot easily download Python programs, each of these two modules is stored with a ".txt" extension which can easily be renamed to ".py" after being downloaded to a Raspberry Pi.

The ADS1115 can also be used in the construction of the PiR2A2 (in my Article 143). It can replace the INA3221 mentioned in that article and shown in the image in Source 19 below.

The adcRead() function has been adapted from the program ADSRunner.py (Source 14) by Guido Lutterbach. His program is much more versatile than adcRead(). Some of the other functions in his program monitor GPIO27 (physical pin 9). When this pin strobes low, the adc reading is taken. To prepare for this, his program uses a pull-up resistor on pin GPIO27. By chance, my PiR2null circuit has a redLED connected to this exact pin. I wondered why this redLED was lit. Well, that's the reason! This strobing is not necessary for the adcRead() function, so I did not implement the pull-up resistor on GPIO27.

Guido's program implements a class of objects with a novel method defined for the class. This method is the main method defined for the object. It permits the programmer to use a predefined cmdLoop() function. Invoking this command loop prompts the user for a 1 character response e.g. "1". The main method analyzes this response and invokes a method called do_1() if the response was "1". In adcRead(), I have replaced this prompt with a simple method mydo_1() which eliminates the prompt completely. The adcRead() function simply returns the value read to the program that called adcRead(). The calling program can then print out the value read (or use it for other purposes).

The PiR2null device mentioned above has only two components: a redLED and a photoCell. The photoCell measures the ambient light. If connected to an RPi input GPIO pin, it senses presence or absence of light (Light or Dark) as a binary signal named digLight(). But when connected to the ADS1115 board and the adcRead() function, the actual amount of light can be read as an analog value. This is easily done using the KY-18 photoCell device that is included in the Arduino Sensor Kit described in Article 147 (Source 15).

Use the "shebang" to easily run a Python program in Terminal

The shebang or hashbang is a Unix trick that simplifies the running of any Python program from the command line. It also permits any Python program (that uses "stdin" and "stdout" etc. for piping) to run at the command line using standard piping syntax. As of 2022CMar18 for OS buster on the Raspberry Pi, the shebang is defined as follows:
#! /usr/bin/python3
The shebang line must be the first line of any program using this Unix "trick". The "quick and easy" copy of the "IX_textnames.py" (the program that lists the files in an IX package) is called "n.py". To easily list the names of all the files in the "IX_textpack_pkg.py" package (presuming it is in the Desktop folder) simply type:
>$ cd Desktop
>$ ./n.py < IX_textpack_pkg.py
It will list the filenames (as shown above just before the "Python Packages" heading). To tell Unix or Linux to run such programs in "quick Terminal" mode, the following command is needed once:
>$ cd Desktop
>$ sudo chmod +x n.py

Variations of Python's "import" syntax

The exact syntax used in the Python "import" has different effects. The different syntax versions are as follows:
	# needs to have adcRead_pkg.py in the same folder as adcRead_test.py
	# needs from adcRead_pkg import adcRead,adcReadInit
	# needs cd Desktop
	
        #Import syntax A
	# from adcRead_pkg import adcRead,adcReadInit
	#   (only lets the program directly call the listed routines)

        # or
        #Import syntax =B	
	# 
	# from adcRead_pkg import *
	#    (lets the program directly call any of the routines in the pkg)
	
        # or
        #Import syntax C
	# 
	# import adcRead_pkg
	#    (to call any imported routine in the pkg using this syntax,
	#     the name of the routine must be preceded by "adcRead_pkg." )
	
        #When using Import syntax A:
        #
	#from adcRead_pkg import adcRead,adcReadInit   #(actually its name is adcRead_pkg.py)
The "import" statements shown above apply to packages that are imported from the local computer, not from packages that are external to the computer. To be made available to any web-surfer "External Packages" must be carefully prepared and uploaded to a site recognized by the creators of python. For example, certain "help information" must be included. Although, they may apply to "External Packages", this article only reports results of the testing of "nonExternal Packages", those created by a programmer who stores them on his/her local computer in the same folder as the main application program. There are 3 different ways of importing functions. They are shown below:

# Import Syntax A
#from adcRead_pkg import adcRead,adcReadInit
#   (only lets the program directly call the listed routines)

# or
# Import Syntax B
#from adcRead_pkg import *
#    (lets the program directly call any of the routines in the pkg)

# or
# Import Syntax C
#import adcRead_pkg
#    (to call any imported routine from the pkg using this syntax,
#     its name must be preceded by the package name: "adcRead_pkg." )
The package named "adcRead_pkg.py" contains 2 externally callable functions named adcRead,adcReadInit. Syntax A and Syntox B can be used to import these 2 functions. Many other internally called functions also exist in the adcRead_pkg.py. They are also imported regardless of which of the 3 Import syntax is used. The program that uses the 2 adcRead functions will function correctly regardless of which Import Syntax is used. However, if the user accidentally defines a function having the same name as a function that already exists in the adcRead_pkg, Python may have difficulty deciding which function to use. Syntax A will "hide" the function in the package, so Python will only use the function defined by the user. Syntax C requires that the user prefix the function from the package with the name of the package if that function is to be used. Syntax C will use the function defined by the user, if no package prefix is used. Syntax B might be confused as to which function to use. Therefore I try not to use Symtax B. I hate having to prefix my function-names with the package-name so I refrain from using Syntax C. Therefore I recommend that users use Syntax A. Notice that the package name specified in the import statement omits the ".py" and must not include pathing information specifying a path to the package.

If a package includes other internally-called functions or class & method information (in addition to the externally callable functions), that infomation can be seen by printing the full contents of this user-defined package. This information (nor the actual definitions) are not easily viewed when external web-based packages are used.

Note that Syntax C requires a package name prefix for each function referenced by the user. Furthermore, globals defined in such packages can also be accessed (set or referenced) by also using the package name prefix.

Another use of the import is shown below:
import adcRead_v13 as adcRead
If the user has different versions of a function available, he can distinguish which version he/she wishe to use by using the word "as" in the the import statement. I have not experimented with the use of the word "as" in the import statement. Note that I have made a version of the IX_textnames.py with the name "n.py". I made this program callable from the terminal command line by using the "chmod" command. I have included the "shebang comment" as the first line of the n.py so that it can be used in bash commands in terminal mode. For me, this facilitates listing most of the notable names included in any IX_package. To list the names of all functions in the IX_package named IX_textpack_pkg.py (in the current folder), I only need to type the command shown below:

>$ ./n.py < IX_textpack_pkg.py
Don't forget to include the "<" when using "n.py" (as I often forget to type it.) It took me considerable research to discover that I needed to prefix the "n.py" with "./" for the "shebang" (aka "hashbang" ) to work.

nShowDefs()

The nShowDefs.py function (Source 16) is a deprecatred version of the n.py. The program, nShowDefs.py, like n.py, lists all the import files (modules) contained in an IX_package. The difference was that nShowDefs.py also lists the function definitions in the IX_package. The program n.py is much more powerful. For example, if the target file is adcRead_pkg.py, all the function definitions will be listed, as shown below:
pi@raspberrypi:~/Desktop $ ./n.py < adcRead_pkg.py
#::: Be sure to precede the Pkg name with a "<".
#::: n.py v03 reports the def's
adcRead_pkg.py
 def MUX(n):
 def swap2Bytes(c):
 def prepareLEconf(BEconf):
 def LEtoBE(c):
 def BEtoLE(c):
 def resetChip(RESET_ADDRESS, RESET_COMMAND):
     def alerted(self, arg):  
     def do_q(self, arg):
     def mydo_1(self,BUS,AINn):
     def shutdown(self):
 def adcRead(BUS,nChannel=0) :
 def adcReadInit(I2C_BUS=1,icNumber="ADS1115") :
#::: end of list of nShowDefs.py
It is interesting to see that some of the "def"s listed above have a first argument of "self". These "def"s are methods defined for a class (even though the "class" statement might not listed.)

In fact n.py will still list all of the function definitions ("def"s) in any Python program, even if the Python program is not a package.

n.py Modified To List Diverse Package Information

n.py is a very useful routine to list information about a package. A good example is the following command:

 ./n.py -h < adcRead_pkg.py 
This is the "help: command for the IX_textpack_pkg.py system. It will return the following:
>$ ./n.py -h any
>$
>$ #:::: Help for python n.py [IX pkg nameslist.py prgm]
>$ #:::: Syntax: ./n.py [args] < pkg
>$ #:::: args=acdghimosuv_
>$ #:::: a:all,c:class,d:def,g:global,h:help,i:import,m:marker,o:OReilly,s:source:,
                  u:used functions,v:v_ versions eg ixv_",_:"__" Dunder-names (Source 17)
>$ #:::: marker is #:::::::::textpak=>
>$ $:::: NB Use IX_textpack.py to create a package.
>$ $:::: ( Cudos to O'Reilly for textpack.py ) 
>$

Improved Package Info Available From n.py

Recent improvements to n.py now give a very impressive overview of a whole package. A Table of Contents (ToC) can now be inserted at the beginning of a package. This ToC lists the importable (marked) files in the package. The ToC also shows which functions are defined in each importable section. The ToC also shows the beginning line number of each item that is listed. An example of a simple ToC is shown below:

pi@raspberrypi:~/Sandbox $ python3 n.py -md < adcRead_pkg.py
#::: Enhanced n.py v02 [IX pkg names list prg -h for help]:
# 1 m adcRead_pkg.py
# 26   def MUX(n):
# 34   def swap2Bytes(c):
# 39   def prepareLEconf(BEconf):
# 45   def LEtoBE(c):
# 53   def BEtoLE(c):
# 60   def resetChip(RESET_ADDRESS, RESET_COMMAND):
# 83       def alerted(self, arg):  
# 90       def do_q(self, arg):
# 94       def mydo_1(self,BUS,AINn):
# 143       def shutdown(self):
# 151   def adcRead(BUS,nChannel=0) :
# 200   def adcReadInit(I2C_BUS=1,icNumber="ADS1115") :
# 230 eof
#::: end of list by n.py v02
Another improvement is that n.py can list the functions that are called by each of the routines in the package. This can be a very long list. An effort has been made to exclude the most-common standard Python functions from this list. The list is called the used-function list. By not listing the Python-defined functions, the remaining functions listed are primarily those that are defined in the routines that are imported. An example of the output excluding the 'used functions" is shown below:

pi@raspberrypi:~/Sandbox $ python3 n.py -a < adcRead_pkg.py
#::: Enhanced n.py v02 [IX pkg names list prg -h for help]:
# 1 m adcRead_pkg.py
# 9  import cmd, time, logging, smbus, RPi.GPIO as GPIO
# 11   #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/  #DC
# 16   #   BUS = adcReadInit(I2C_BUS,icNumber)    # create BUS class object
# 26   def MUX(n):
# 34   def swap2Bytes(c):
# 39   def prepareLEconf(BEconf):
# 45   def LEtoBE(c):
# 53   def BEtoLE(c):
# 60   def resetChip(RESET_ADDRESS, RESET_COMMAND):
# 65   class ADS1115Runner(cmd.Cmd):
# 83       def alerted(self, arg):  
# 90       def do_q(self, arg):
# 94       def mydo_1(self,BUS,AINn):
# 129               global g_adcValue
# 143       def shutdown(self):
# 149   #class end ADS1115Runner()
# 151   def adcRead(BUS,nChannel=0) :
# 162       #Source: https://smartypies.com/projects/ads1115-with-raspberrypi-and-python/ads1115runner/  #DC
# 173       #   GPIO.        for ALERTPIN  class is not used  #DC
# 192           global g_adcValue
# 200   def adcReadInit(I2C_BUS=1,icNumber="ADS1115") :
# 203       # usage of global variables
# 204       # global g_adcValue
# 230 eof
#::: end of list by n.py v02
The small additions are the "import", "class" and "source:". Even the class methods can be identified by their first argument of "self". Even the names of the "passed parameters" are visible. The occassional line of "noisy" information appears (such as the word "class" in the "GPIO" line. But the truly useful information outweighs this noise, imho.) The output generated by n.py that includes the used-functions can be quite long. Below, I will only cite the functions used (called) by the class. The functions used (called) by the methods defined by the class definition are:

# 65   class ADS1115Runner(cmd.Cmd):
# 65    ADS1115Runner()
# 66    cmdloop()
# 68    cmdLoop()
# 78    do_1()
# 78    do_2()
# 83    alerted()
# 83       def alerted(self, arg):  
# 85    read_word_data()
# 88    alerted()
# 90    do_q()
# 90       def do_q(self, arg):
# 92    do_q()
# 94    mydo_1()
# 94       def mydo_1(self,BUS,AINn):
# 106    resetChip()
# 107    write_byte()
# 112    prepareLEconf()
# 114    MUX()
# 115    prepareLEconf()
# 119    write_word_data()
# 124    read_word_data()
# 125    LEtoBE()
# 129               global g_adcValue
# 130    adcRead()
# 132    test_adcRead()
# 141    mydo_1()
# 143    shutdown()
# 143       def shutdown(self):
# 147    shutdown()
# 149   #class end ADS1115Runner()
The output shown above is the actual uneditted output from n.py. It is truly remarkable how good an overview one gets when all of the "used" functions are listed in the order that they are called. If one is familiar with the nature of the purpose of the class definition, the overview is very informative.

Unix-like Command-list Arguments For n.py

Another improvement is that the various types of output that can be generated by n.py do not require many different programs. A command list [args] has been added to n.py that permits the user to select which information is to be output by n.py. The full command list for n.py is "-acdghimosu_". The type of output generated by each "letter" in the command list is shown below:

a  all  (a:   outputs all except "u")
        (all  outputs all info including "u")
c  class
d  def
g  globals
h  help
i  imports
m  marked files
o  O'Reilly-marked files
s  sources (Source:)
u  used-functions (routines called)
v  version definition "v_" e.g. "ixv_=3"
_  double underscore ("__" e.g. __name__ or __init__ )
The amount of information that can be produced is truly impressive. The command list can contain an underscore (i.e. "_"). This is not included in "a" nor in "all". But "_" can be combined with any other command line letters. Very few of my programs make use of the "__" system variables. But the "_" commmand is available to search for "__" variables if needed by anyone in the future.

It is also advantageous that the actual real-time line numbers are shown. Comparing a ToC (that has been editted into the package) with a current listing will show if the package has had any lines added or removed. The addition of a simple"checksum" is being considered.

From time-to-time one might encounter a textpack package that was created using the original O'Reilly markers. The n.py program provides a great deal of information, even for the O'Reilly files. But such O'Reilly files will need a small amount of editting in order for the IX_textpack routines to extract (select) members of the O'Reilly packages.

In conclusion, the n.py is very useful when digging into a package or even a program, starting from the high level bird's eye or satellite view. More and more details can be requested in the command list, giving a better and better "view" of the package or program.

Version control of Functions in Packages

Over time, multiple versions of the same functions can accumulate in a package. Unless the packages are manually editted, the newer modules are positioned later in the package. Fortunately, Python doesn't "choke" when multiple versions are encountered. Python sensibly uses the last version that it encounters. The author is experimenting with a method of version control of functions contained in a package. There appears to be a way of doing this, while providing a mechanism that lets the main program know of the version of each function that is in use. When the help file is output by the n.py program, it shows the version numbers of the main functions used by the n.py routine. However, the more simple output from n.py is not "cluttered" by the inclusion of software version numbers.

My Version Control with Python Packages

When computer systems become complex, version control becomes important. The author has decided to incorporate version control as a mandatory part of his Python software. Version control can be implemented merely using comments in software, but it is even better when the software can use (report) versions within the software. One way to do this is by adding an additional OPTIONAL parameter to each function or subroutine call. In Python, an additional parameter can be "pre-defined" with a given value. If this is done, the calling program can ignore (not even mention) this additional parameter. This means that any software calling (using) a function can ignore version control completely. By including the additional parameter as "?" when calling, the calling program can "make use of" the version number and report it, for example, in a print statement as shown below. The version number is returned as an integer (not a string variable) to the calling program. Therefore, if the function called is passed an extra last (version) argument of v="?", the function will return the version number as a second (unusual) argument.

The sensible use of Version Numbers in software requires that the different versions of the software be retained and be accessible. It also means that the calling programs can function correctly without making any reference to the version numbers, especially NOT needing to make use of the version number as part of the name of the function being called. The author uses the version number syntax ( noting the use of "ixv_=" ) illustrated below:

#def functionList(testStr="", v="") :
    #pass;                 ixv_=3
    #returnValue=functionList_v03(testStr)
    #if v=="?" : return returnValue,ixv_
    #return returnValue
#def end

#def functionList_v03( testStr) :
    # by D@CC on 2022DApr07
    #. . . .
    #. . . . function definition statements go here
    # . . . .
    #return anyValue
#def end functionList_v03

def mainroutine() :
    #main program used to test the functionList function

    from functionList_pkg import functionList

    ixv_=17                #ixv_ is the version of t.py
    line="abc = aStr(1000*unixTime() ) + bigI(333)"
    print("line:"+line+":")
    fList=functionList(line)
    for x in fList : 
        # python3 is needed for end= below
        print(x, end=" " )
    #for end
    print()
    print("vsn of t.py: ",ixv_)
    print( "vsn of functionList: ", functionList("",v="?")[1])
    return
#def end
if __name__ == '__main__'  : mainroutine()
#end of t.py ixv_=17
In the above program, note that:

1. The main program does not include the version number of the function named "functionList". 2. The main program does not need to cite the extra (last) argument, the version number. 3. The version number of "functionList" can be obtained and output. 4. The program references "functionList" but the actual function used is "functionList_v03". 5. The actual version number "3" appears in source code mandatorily in only 2 "nearby" places. 6. The above program will print: >$ line:abc = aStr(1000*unixTime() ) + bigI(333): >$ aStr unixTime bigI >$ vsn of t.py: 17 >$ vsn of functionList: 3

List of Python Modules (Functions) Used By PiR2

GENERAL-PURPOSE MODULES
  Module                        returns             calls/Uses          args   
  ********************          *********           **********          *******
  acquire_buttonPush()          0 if Down           obj GPIO            btn_pin
  acquire_digIn0()              1 if High           obj GPIO            btn_pin     
  acquire_piIP()                IPstr               osCommand()         none
  acquire_piOS()                OSstr               osCommand()         none
  acquire_piSN()                SNstr               osCommand()         none
  acquire_procTemp()            Tempstr(C)          osCommand()         none
  add_event_detect()            na                  obj GPIO            comment
  askVerbose()                  False if Verbose    input()             isQuerrying
  control_audioTV()             na                  osCommand()         sound fileName
  control_digOut0()             na                  obj GPIO            do_pin,onOne
  control_piArea()              na                  g_piAreaStr         roomStr
  control_redLED()              na                  obj GPIO            pin,onOne
  helloTask()                   na                  na                   na
  informUserWait()              na                  time                isVerbose,DT,down5
  isLogAvailable()              na                  os,askVerbose       logfileName
  manageTasks()                 na                  g_startTimeArray    na
  osCommand()                   reply               os, g_fileArray     commandStr
  queuehelloTask()              na                  g_startTimeArray,   na
                                                    g_hellloTaskNumber,
                                                    unixTime()                                 
  sortableDateTime()            DateTime str        time. parts         timeIn
  unixTime()                    tStr                time. str()         na

PYTHON & EXTERNAL MODULES
  Module                        returns             calls/Uses          args  
  ********************          *********           **********          *******
  .exists()                     True if exists      os.path.            fileName
  .input()                      True if HIGH        obj GPIO.           pin
  .isnumeric()                  True if digits      anyStr.             na
  .output()                     na                  obj GPIO.           pin,1/0
  .setmode()                    na                  obj GPIO.           p/b
  .setup()                      na                  obj GPIO.           pin,I/O,i=1
  .strftime()                   str                 time.               %Y &m etc

PiR2-SPECIFIC MODULES
  Module                        returns             calls/Uses          args  
  ********************          *********           **********          *******
  appendToLog()                 pir2-specific
  array()                       pir2-specific
  control_fromOwner()           pir2-specific
  createLogCopy()               pir2-specific
  createNewEmptyLogTask()       pir2-specific
  displayHeader()               pir2-specific
  displayLog()                  pir2-specific
  getControl_fromOwner()        pir2-specific
  getsize()                     pir2-specific
  identifyTask()                pir2-specific
  initializeTask()              pir2-specific
  openLog2()                    pir2-specific
  piR2_attrFromStr()            pir2-specific
  pir2_convertMIC_ControlTask() pir2-specific
  piR2_findStrInArray()         pir2-specific
  pir2_initGPIO()               pir2-specific
  piR2_ioDeviceAttribute()      pir2-specific
  pir2_performAorC()            pir2-specific
  pir2versions()                pir2-specific
The modules listed above include both general-purpose functions that can be used elsewhere and specific modules for the PiR2 control system. This list was created using routines n.py and stripWord1.py A description of each general-purpose function will be added at a later date.


This article, by D@CC, is of course, a work-in-progress as of 2022DApr07.

End of Article (Sources follow)

External Sources

Video Sources

Video Source 01:www na by

Web Sources

Web Source S174:01:www Thonny: The Beginner-Friendly Python Editor Krishelle hardson-Hurley
Web Source S174:02:www Title: Create and Access a Python Package By Chinmoy Lenka On 15 Feb, 2018 (NB This works for Python not for Thonny)
Web Source S174:03:www Latest PiIX07 Package Programs (zipped) By David Cole on 2022BFeb28 ( in Thonny)
Web Source S174:04:www Global and isTypeStr Subroutines (in a txt file) By David Cole on 2022CMar03
Web Source S174:05:www IX_py Python Functions (Comprehensive list) By David Cole on 2022CMar12
Web Source S174:06:www IX_package_py_py.txt (IX Python Function Library) (unpack using IX_textunpack.py) By David Cole oas of 2022CMar12
Web Source S174:07:www textunpack_py.txt (deprecated by Source 10) By David Cole as of 2022CMar12
Web Source S174:08:www Packing and Unpacking Files By O'Reilly
Web Source S174:09:www What's New in Python 3 By Tutorials Point
Web Source S174:10:www IX_textpack_pkg_py.txt (7 files) By David Cole as of 2022CMar17
Web Source S174:11:www Package adcRead_pkg_py.txt By David Cole as of 2022CMar16
Web Source S174:12:www adcRead_test_py.txt By David Cole as of 2022CMar16
Web Source S174:13:www SeeedStudio Forum See Raspberry Pi question by David Cole as of 2022CMar16
Web Source S174:14:www ADS1115Runner.py By Guido Lutterbach as of 2020
Web Source S174:15:www Arduino: 37 Sensor Kit (Article 147) By David Cole as of 2021DApr16
Web Source S174:16:www nShowDefs() By David Cole as of 2022CMar19
Web Source S174:17:www Python Dunders and "_"s By Rachit Tayal 2019HAug06
Web Source S174:18:www Python's 33 Reserved Keywords By Artturi Jalli 2021L28
Web Source S174:19:www PiR2A2DrawA05.jpg Image by D@CC on 2020FJun 18




WebMaster: Ye Old King Cole

Click here to return to ePC Articles by Old King Cole

Date Written: 2022 B Feb 26
Last Updated: 2024 B Feb 26

Backed Up On: 2022 D Apr 08 as 174_2022DApr08.html
Should edit using EditPad Lite 8 using Consolas (or Courier) Font (monospaced)
© ICH180RR Corp.

/174.html