Nesting multiple modules within a module in script?

358
6
10-15-2021 08:30 AM
RPGIS
by
Regular Contributor

Hi,

Just a simple question, is it possible to have multiple python modules nested within a python module? I am working on a script tool and I was thinking of nesting multiple modules within a module, but I just wanted to check to see if this is either frowned upon when it comes to scripting or if there is some other reason not to do it.

0 Kudos
6 Replies
BlakeTerhune
MVP Regular Contributor

I'm not sure what you mean. Are you referring to having multiple imports or creating multiple function defs? Because both of those are normal (encouraged) practices. Could you give a pseudo code example?

DonMorrison1
Occasional Contributor II

If you are talking about python modules within a python toolbox and you plan to publish the tool to an ArcGIS server, then my experience is that any custom python modules you import have to be at the same level as the toolbox itself.  This has to do with the consolidation that happens during the publishing step, the ESRI code has to find all of the dependent modules and move them to the server. The consolidation code does not look in subdirectories for those dependent modules.

If you are not going to be publishing the tool then I don't see any problem importing modules in a subdirectory (not sure if this is what you are asking about).

Luke_Pinner
MVP Regular Contributor

A module is always a single python file (which can contain multiple classes and functions inc. nested classes and functions).  You can't nest modules per se.  You can create a package though, which is a directory with an __init__.py and other .py files, and optionally nested sub-directories each with an __init__.py and other .py files (ignoring the newer "namespaces packages" which I don't know much about). 

From the doc:

 

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      etc...

 

 

When you import os.path or arcpy.sa etc... this is using a subpackage.

0 Kudos
RPGIS
by
Regular Contributor

Ok so, if I understand this correctly, is that a script and module are technically one in the same and that nesting multiple modules is not possible. However, nesting multiple classes is possible. Here is what I was originally thinking.

def sample(a):
    b = a
    return b

    def example(c):
        c = l
        # do something
        return c

If something like this isn't necessarily proper, but setting these to classes instead of modules is then I will give that a try. I was trying to figure out the best approach since I am trying to create a custom tool(s) for my department to utilize in the web. So far, the tool seems to work perfectly without nesting anything additional, but I was simply curious is all.

0 Kudos
Luke_Pinner
MVP Regular Contributor

@RPGIS wrote:

Ok so, if I understand this correctly, is that a script and module are technically one in the same and that nesting multiple modules is not possible.


Yes a script and module are both just a single python file, it's more a matter of convention that scripts contain code that gets executed and modules usually just contains functions, classes and constants that are imported by other modules and scripts.


@RPGIS wrote:

However, nesting multiple classes is possible. Here is what I was originally thinking.

 

def sample(a):
    b = a
    return b

    def example(c):
        c = l
        # do something
        return c

 

That is a function with a nested function, not a class.  What you have there will not work. The example function can only be called from within the sample function but you return a from the sample funcction without doing anything with the example function. 

Try and run that example and call example('something') you'll get a NameError: name 'example' is not defined

I think you should read up on "namespaces" before you start trying this sort of thing.

0 Kudos
RPGIS
by
Regular Contributor

hi @Luke_Pinner,

I was simply asking out of curiosity. I wasn't necessarily planning on going in that direction without checking with someone who is more knowledgeable than I. I am glad that the documentation that you provided outlined the different setups in regards to namespaces. I am relatively new to scripting functions and classes, so I do not have quite a strong grasp of such concepts.

I will have to do some more research to figure out which direction would be best to take as well as experiment to see how script will behave.

There is still a lot of material in regards to all of the intricacies and functionalities of python as it pertains to GIS. I am still trying to learn what is best practice and I check with the community frequently when I don't fully understand something. 

0 Kudos