Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How to use variables across modules

I'm trying to figure out how to use variables and setups across modules.

Am I right when I think it's smart to keep separate functions of a program in separate modules?

I have a main program module called main.py and in it I have this:

# Sets GPIO's to HIGH = Relays OFF
try:
    import RPi.GPIO as GPIO
except RuntimeError:
    Print("Error importing RPi.GPIO!!")

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
# GPIO16 is relay1
GPIO.setup(16, GPIO.OUT, initial=GPIO.HIGH)
# GPIO11 is relay2
GPIO.setup(11, GPIO.OUT, initial=GPIO.HIGH)

I then import a module (in that module I have a function called Relay) and try to use the function with module1.Relay(1,1)

But the function in module1 needs the GPIO from the main.py to Work. How do I go about with this? I really don't want the GPIO setting part in the module1, I don't want it to be run every time I run the module1.Relay(1,1) call..

What is best practice for working across modules? (I'm making a controller for my home's heat system.)

like image 927
user2948667 Avatar asked Nov 02 '13 21:11

user2948667


1 Answers

You're right about keeping separate functionality of your application in different modules - it absolutely makes sense to group your code in logically related units. That's not always trivial though, and forces you to clearly think about that depends on what, and separation of concerns. What you've come across here is called a circular import.

There's two obvious ways to resolve circular imports:

  • Extract the thing that's shared by more than one module, and put it in its separate module. In your case that's the GPIO including its initialization.
  • Don't import the thing that's shared in every module, but instead import it once and pass it as an argument to other things that need it.

Extracting it into its own module

Extracting the GPIO initialization into it's own module could look like this:

main.py

from gpio import GPIO
import module1

print "main: %s" % GPIO.__name__
# Do stuff wth GPIO

module1.Relay()

gpio.py

# Sets GPIO's to HIGH = Relays OFF
try:
    import RPi.GPIO as GPIO
except RuntimeError:
    print("Error importing RPi.GPIO!!")

print "Setting up GPIO"
GPIO.state = 'initialized'
print "Done setting up"

module1.py

from gpio import GPIO

def Relay():
    print "Relay: %s" % GPIO.__name__
    # Do stuff with GPIO

Output when running main.py:

Setting up GPIO
Done setting up
main: RPi.GPIO
Relay: RPi.GPIO

As you can see, the GPIO initialization in the global scope of the gpio.py module is run only once, on the first occasion the module is imported anywhere.

Passing as an argument

The other option, importing GPIO once and passing as an argument could look like this:

main.py

# Sets GPIO's to HIGH = Relays OFF
try:
    import RPi.GPIO as GPIO
except RuntimeError:
    print("Error importing RPi.GPIO!!")

print "Setting up GPIO"
GPIO.state = 'initialized'
print "Done setting up"

import module1

print "main: %s" % GPIO.__name__
# Do stuff wth GPIO

module1.Relay(GPIO)

module1.py

def Relay(gpio):
    print "Relay: %s" % gpio.__name__
    # Do stuff with GPIO

Both are valid ways in your case, in my opinion. I personally would prefer to have the initialization in a central gpio.py module and then import from there, but that's just a matter of taste.

like image 61
Lukas Graf Avatar answered Sep 28 '22 07:09

Lukas Graf