I have two source files that I am running in Python 3.9. (The files are big…)
File one (fileOne.py)
# ...
sessionID = uuid.uuid4().hex
# ...
File two (fileTwo.py)
# ...
from fileOne import sessionID
# ...
File two is executed using module multiprocessing.
- When I run on my local machine and print the UUID in file two, it is always unique.
- When I run the script on Centos OS, it somehow remained the same
- If I restart the service, the UUID will change once.
My question: Why does this work locally (Windows OS) as expected, but not on a CentOS VM?
UPDATE 1.0:
To make it clear.
For each separate process, I need that UUID will be the same across FileOne and FileTwo. WHich mean
processOne = UUID in file one and in file two will be 1q2w3e
processTwo = UUID in file one and in file two will be r4t5y6 (a different one)
2
Answers
When you run your script it generate the new value of the uuid, but when you run it inside some service you code the same as:
so to fix the issue you can try wrap the code to the function, for example:
in you second file:
Your riddle is likely is caused by the way multi-processing works in different operating systems. You don’t mention, but your "run locally" is certainly Windows or MacOS, not a Linux or other Unix Flavor.
The thing is that multiprocessing on Linux (and up to a time ago on MacOS, but changed that on Python 3.8), used a system
fork
call when using multiprocessing: the current process is duplicatesd "as is" with all its defined variables and classes – since yoursessionID
is defined at import time, it stays the same in all subprocesess.Windows lacks the
fork
call, and multiprocessing resorts to start a new Python interpreter which re-imports all modules from the current process (this leads to another, more common cause of confusion, where any code not guarded by anif __name__ == "__main__":
on the entry Python file is re-executed). In your case the value forsessionID
is regenerated.Check the docs at: https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods
So, if you want the variable to behave reliably and have teh same value across all processes when running multiprocessing, you should either pass it as a parameter to the target functions in the other processes, or use a proper structure meant to share values across processes as documented here:
https://docs.python.org/3/library/multiprocessing.html#sharing-state-between-processes
(you can also check this recent question about the same topic: why is a string printing 3 times instead of 1 when using time.sleep with multiprocessing imported?)
If you need a unique ID across files for each different process:
(As is more clear from the edit and comments)
Have a global (plain) dictionary which will work as a per-process registry for the IDs, and use a function to retrieve the ID – the function can use
os.getpid()
as a key to the registry.file 1:
file2:
(the setdefault dict method takes care of providing a new ID value if none was set)
NB.: the registry set up in this way will keep at most the master process ID (if multiprocessing is using
fork
mode) and itself – no data on the siblings, as each process will hold its own copy of the registry. If you need a working inter-process dictionary (which could hold a live registry for all processes, for example) you will probably be better using redis for it (https://redis.io – certainly one of the Python bindings have a transparent Python-mapping-over-redis, so you donĀ“t have to worry with the semantics of it)