1

I am trying to figure out global variables in python, and while there are many forum posts and examples, none of them really match what I need. Here is the problem: I am using a MySQL database to receive 11 different variables. These variables are used for control purposes, such as the opening and closing of valves at specific times and days. I need these variables to be global and they must be able to be used in many other files. At the moment, these variables only exist within the file that reads the database and assigns the variables a value.

Here's my question:

When I import the variables from the database, can I simply assign them to be global in that script? Like this:

cursor.execute ("select variable1,variable2,....variableN from transaction where TransactionNumber=(select MAX(TransactionNumber) from transaction)")

readfromdb= cursor.fetchone() 

variable1,variable2,.....variableN=list(readfromdb)

global variable1,variable2...variableN. 

And then import this file in each other file I'm using?

I have tried doing this method, but receive the following error:

SyntaxError: name 'TransactionNumber' is assigned to before global declaration

I am open to other suggestions to make this process more efficient/streamlined. But my only requirement is that the script that is currently reading the database MUST not change. It is a fundamental requirement that it continues reading and assigning the database variables. I won't bore you with details, but that script is vital to checking the data we receive from the database and making sure that it is correctly formatted for use since we will be receiving data from another computer.

BenG
  • 304
  • 1
  • 11
  • Maybe if you do it `global variable1,variable2,.....variableN=list(readfromdb)` – Hackerman Jul 05 '18 at 18:50
  • Why don't you save the values of the variables to a file, which can then be read by other programs. Then all you need to do is update the values in the file when you need to. –  Jul 05 '18 at 18:50
  • Your `global` directive is completely pointless if it is at the global scope. You could fix the SyntaxError by putting that statement at the top, but again, **it is totally pointless**. Python does not support true global variables, only *module global*. – juanpa.arrivillaga Jul 05 '18 at 18:51
  • 1
    So, as the [Python FAQ notes](https://docs.python.org/3.7/faq/programming.html#how-do-i-share-global-variables-across-modules) the conventional way to do this is to move all your desired global variables to their own modules, e.g. `config.py` and then in all the other files where you need them, simply `import config` and use `config.some_global_variable_i_need` wherever you need them. – juanpa.arrivillaga Jul 05 '18 at 18:56

1 Answers1

0

The message has your answer in it. Just move the global statement above the first use of any of the variables.

You'll have to repeat those global declarations at the top of any function that needs to assign new values to any of those names.

Juanpa Arrivillaga makes and excellent point. To share across module boundaries, you'll need to use module names to specify exactly which module they are defined in. The global statement really only helps share names among functions and initialization code in a single module.

If "source1.py" creates a module-level ("global") variable or function name1, and you want to use it in "source2.py", you'll have to import source1 in the source2.py file and then refer to the variable/function as `source1.name1'.

At this point, I really recommend looking at a dictionary or some type of custom class or namedtuple object. You can solve this with globals, but it's going to end up looking like a dog walking on two legs. It's impressive not because the dog does it well, but because the dog does it at all.

I'd use either an object, dictionary or named tuple to hold those fields, so that the whole mess could be passed as an argument to functions. Global variables get messy, particularly in code that gets updated frequently. This gets rid of all of those global statements. The class type for an object or the field list for a named tuple becomes a single point of definition that the whole module can see.

Mike Housky
  • 3,959
  • 1
  • 17
  • 31
  • LOL. Wow I am bad at python. I moved it before the line but forgot I had initialized some of the variables in the first few lines. Sorry for my noobery. –  Jul 05 '18 at 18:57
  • 2
    This would solve the syntax error but not the problem of sharing globals across files. Python doesn't have true global variables (a feature, not a bug), so usually, you just put them in their own `cfg` module and `import cfg` wherever you need them – juanpa.arrivillaga Jul 05 '18 at 18:57
  • @juanpa.arrivillaga sounds good, I will try that. Appreciate the advice. –  Jul 05 '18 at 18:59
  • 1
    @juanpa.arrivillaga Quite right...missed the "...and copy to every other file" part. Updating... – Mike Housky Jul 05 '18 at 19:00
  • 2
    But more importantly, `global` is totally pointless *in the global scope*. – juanpa.arrivillaga Jul 05 '18 at 19:06
  • 1
    @juanpa.arrivillaga Not totally. In a module that uses globals to pass information between functions and/or initialization code, that can be considered "documentation" that those names will be used. Even so, OP wouldn't have got that message if the code was at "file level". So, functions are involved. – Mike Housky Jul 05 '18 at 19:19
  • 1
    @juanpa.arrivillaga And yes, that last bit (no error message at module level) does support your point. At the module level, a global statement is *at best* a comment; and at worst a comment that probably wont be removed by any compiler. – Mike Housky Jul 05 '18 at 19:23
  • 1
    Um, no, that error message would happen exactly like that even at the file level. Try it out. Make sure you are using Python 3.6 (before that, it wasn't an error, and it's only a warning in 3.5). The entire thing is totally unconventional, to put it mildly. – juanpa.arrivillaga Jul 05 '18 at 19:36
  • @juanpa.arrivillaga Alright, now THAT is interesting. It's an error when running module initialization but not in interactive mode. (That's where I tested it, and it is 3.6.1.) Thanks for that info. (Could have been an artifact from using Idle, too, I guess.) – Mike Housky Jul 05 '18 at 19:53