Select to view content in your preferred language

problem using python modules

6533
4
Jump to solution
03-06-2013 03:16 PM
BKS
by
Frequent Contributor
I have a rather basic python question re: modules

I have a python script that's essentially structured as follows:

======================================
## aaa.py

func1():
   ...some code...
...arcpy.AddMessage("message")
...return

func2():
    ...some code...
...arcpy.AddMessage("message")
...return

If __name__ = "main":

...import sys, arcpy, argparse, os, time
   
    ...some code...
...func1()
...func2()
...return
======================================

I want to write another script that uses the functions within aaa.py.  So I import aaa.py as a module into this other script (see bleow).

======================================
## bbb.py

import sys, arcpy, argparse, os, time, aaa
   
some code...
aaa.func1()
=======================================

When I execute aaa all is fine.
When I execute bbb, it returns an error "NameError: global name 'arcpy' is not defined". 

Appreciate any insight on how to avoid this.

b

PS - used ... in post above to show indent since spaces and tabs removed
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
by Anonymous User
Not applicable
Hello Caleb1987,
Although I DO import arcpy into both aaa.py and bbb.py, you've made me realize why I'm getting the error I think.

That is, when I run bbb.py which imports both arcpy and aaa.py, and attempt to execute aaa.func1(), the reason there is a problem with aaa.func1() not recognizing 'arcpy' is that it never gets imported into aaa.func1() since it's only imported in aaa.py when name == __main__ (i.e. when executing aaa.py directly). 

So I do get this.  But what is the solution then?

Should I add "import arcpy" to each function within aaa.py ?  This does solve the problem but it doesn't seem like the right thing to do.  Not sure if this will create any issues (performance or otherwise).


Interesting you mention this....True, you do import arcpy in aaa.py, BUT you only import it IF the name is main.  So rather than doing it that way, you need to put the import arcpy at the very top above your def statements even (or at least above the name == main part).  Otherwise arcpy only gets imported if the name is main.  Do you see what I mean?

So instead of

 def func1():     # do something  if __name__ == '__main__':     import arcpy          # this only gets imported when name is __main__     func1()


Do THIS:

import arcpy       # this way arcpy is ALWAYS imported  def func1():     # do something  if __name__ == '__main__':      func1() 


This will be what makes the difference

View solution in original post

0 Kudos
4 Replies
by Anonymous User
Not applicable
This was difficult for me to understand at first as well.  The top level program is the module that has all of your functions living inside of it (aaa.py in your case).  It does not appear that you have imported the arcpy module into your "aaa.py" script.  You need to do this at the top of this module.  Even though you have imported arcpy in bbb.py, this is outside the scope of the functions you are importing from aaa.py.  Anything outside of a function is a global variable, anything inside of a function is a local variable.  If you have functions without any input parameters, they simply cannot "see" any of the global variables that are outside of its scope, i.e. outside of the function.  You can see the name of the module that any function when you import it into another program with this simple test:

# aaa.py

import arcpy

def func1():
    # some code
    print 'Name =  %s' %__name__
    arcpy.AddMessage('Name =  %s' %__name__)
    return


func1()


This will return:


>>> Name =  '__main__'



Whenever you execute this function in top level module the __name__ will always be '__main__'  whenever you run the aaa.py. However, if you import this function into bbb.py and run it you will get a different result:

# bbb.py

import aaa

aaa.func1()


This will return:


>>> Name =  'aaa'



This is true because the __name__ from where func1() lives is always 'aaa', UNLESS it is ran inside "aaa.py", then the name will be '__main__'.

The only ways (that I know of, there are probably more ways) that you can pass global variables into functions is to pass them in as parameters or declare them as a global variable.  If you import arcpy into your aaa.py file, you should be able to call it inside of another module without having the error on importing arcpy (for running func1() that uses arcpy) in bbb.py.  Anything outside of the functions from aaa.py will be able to access the import arcpy at the top of bbb.py

Conversely, the same can be true in the opposite case.  I imported arcpy into my 'aaa.py' script.  When I import aaa and call func1() arcpy is only available inside func1() because arcpy is not imported in bbb.py, even though arcpy is associated with aaa.func1().  If you want to use arcpy in bbb.py, it must be imported into this as well.

Whenever I write modules that contain functions I will use the "if __name__ ==  '__main__' " at the bottom so I can test the functions to make sure they work with some sample input variables.  That way whenever they are imported into another module the sample variables under the if name = main part of the top level module will not be used because the functions __name__ will never be __main__ when it is ran in another module.  I hope this makes sense.
0 Kudos
BKS
by
Frequent Contributor
Hello Caleb1987,

Thanks for all of that info.  I did know some of that but it's good to get more info and is appreciated.

Although I DO import arcpy into both aaa.py and bbb.py, you've made me realize why I'm getting the error I think.

That is, when I run bbb.py which imports both arcpy and aaa.py, and attempt to execute aaa.func1(), the reason there is a problem with aaa.func1() not recognizing 'arcpy' is that it never gets imported into aaa.func1() since it's only imported in aaa.py when name == __main__ (i.e. when executing aaa.py directly). 

So I do get this.  But what is the solution then?

Should I add "import arcpy" to each function within aaa.py ?  This does solve the problem but it doesn't seem like the right thing to do.  Not sure if this will create any issues (performance or otherwise).

Any thoughts?

Cheers, b
0 Kudos
by Anonymous User
Not applicable
Hello Caleb1987,
Although I DO import arcpy into both aaa.py and bbb.py, you've made me realize why I'm getting the error I think.

That is, when I run bbb.py which imports both arcpy and aaa.py, and attempt to execute aaa.func1(), the reason there is a problem with aaa.func1() not recognizing 'arcpy' is that it never gets imported into aaa.func1() since it's only imported in aaa.py when name == __main__ (i.e. when executing aaa.py directly). 

So I do get this.  But what is the solution then?

Should I add "import arcpy" to each function within aaa.py ?  This does solve the problem but it doesn't seem like the right thing to do.  Not sure if this will create any issues (performance or otherwise).


Interesting you mention this....True, you do import arcpy in aaa.py, BUT you only import it IF the name is main.  So rather than doing it that way, you need to put the import arcpy at the very top above your def statements even (or at least above the name == main part).  Otherwise arcpy only gets imported if the name is main.  Do you see what I mean?

So instead of

 def func1():     # do something  if __name__ == '__main__':     import arcpy          # this only gets imported when name is __main__     func1()


Do THIS:

import arcpy       # this way arcpy is ALWAYS imported  def func1():     # do something  if __name__ == '__main__':      func1() 


This will be what makes the difference
0 Kudos
BKS
by
Frequent Contributor
Thanks - that's so obvious I didn't see it.

Appreciate your patience.

b
0 Kudos