jdoedoe
jdoedoe

Reputation: 11

Python module global variables

I have a following code but I want to transform it into module. Obviously if I miport this code as module ser_r and ser will never be initialized and the Agent class won't work.

#module.py

class Agent:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def send(self, data):
        message = data + ' ' + a
        ser.write(message)

ser_r = serial.Serial(
                    port='COM6',
                    baudrate=500000,
                    parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE,
                    bytesize=serial.EIGHTBITS
                    )

ser = io.TextIOWrapper(io.BufferedRWPair(self.ser_raw, self.ser_raw, 1),
                   newline='\r',
                   line_buffering=True)

So I came up with the idea to create class Serial which has ser variable which is then used in Agent class.

But now there is another problem: How do I access Serial inside Agent without creating instance of Serial? The user can create a Serial instance but then I don't know the name I should use inside Agent. I can make init method and then create Serial class inside. After importing user would call init method and then he could use it.

#module.py

class Agent:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    def send(self, data):
        message = data + ' ' + a
        Serial.ser.write(message)



class Serial:
    ser_r = serial.Serial(
                port='COM6',
                baudrate=500000,
                parity=serial.PARITY_NONE,
                stopbits=serial.STOPBITS_ONE,
                bytesize=serial.EIGHTBITS
            )

    ser = io.TextIOWrapper(io.BufferedRWPair(self.ser_raw, self.ser_raw, 1),
                               newline='\r',
                               line_buffering=True)

Upvotes: 0

Views: 432

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121992

Obviously if I import this code as module ser_r and ser will never be initialized and Agent class won't work.

No, that's not obvious at all, and in fact wrong. Importing a module runs all top-level code. There is no problem here, ser_r and ser are created along with everything else.

Classes are not special here; class Serial: ... is just another top-level statement, just like the ser_r and ser assigment statements.

Note that the module forms the global namespace for all code in that module. In Agent.send(), the name ser is a global, and that name is resolved by looking at the attached module globals where ser will already exist.

You do have an error in the code, however:

ser = io.TextIOWrapper(io.BufferedRWPair(self.ser_raw, self.ser_raw, 1),
                   newline='\r',
                   line_buffering=True)

There is no global name self defined, so self.ser_raw doesn't exist either. Perhaps you meant to create the wrapper around ser_r instead?

ser = io.TextIOWrapper(io.BufferedRWPair(ser_r, ser_r, 1),
                       newline='\r', line_buffering=True)

This all means you don't actually have to use the Serial class. It has no state (only class attributes), so you'd never need to create an instance anyway, you could just treat it as a global (as your second attempt already does). Because you already have access to the Serial global from Agent().send(), there is no need for anyone using your module to have to know about Serial or create an instance of it.

If you do not want to make the serial connection a global, you could always create the connection in Agent.__init__(), or have that class accept a suitable io.TextIOBase object to write to.

Upvotes: 3

Related Questions