Hello generous SO'ers,
This is a somewhat complicated question, but hopefully relevant to the more general use of global objects from a child-module.
I am using some commercial software that provides a python library for interfacing with their application through TCP. (I can't post the code for their library I don't think.)
I am having an issue with calling an object from a child module, that I think is more generally related to global variables or some such. Basically, the object's state is as expected when the child-module is in the same directory as all the other modules (including the module that creates the object).
But when I move the offending child module into a subfolder, it can still access the object but the state appears to have been altered, and the object's connection to the commercial app doesn't work anymore.
Following some advice from this question on global vars, I have organized my module's files as so:
scriptfile.py
pyFIMM/
__init__.py # imports all the other files
__globals.py # creates the connection object used in most other modules
__pyfimm.py # main module functions, such as pyFIMM.connect()
__Waveguide.py # there are many of these files with various classes and functions
(...other files...)
PhotonDesignLib/
__init__.py # imports all files in this folder
pdPythonLib.py # the commercial library
proprietary/
__init__.py # imports all files in this folder
University.py # <-- The offending child-module with issues
pyFIMM/__init__.py
imports the sub-files like so:
from __globals import * # import global vars & create FimmWave connection object `fimm`
from __pyfimm import * # import the main module
from __Waveguide import *.
(...import the other files...)
from proprietary import * # imports the subfolder containing `University.py`
The __init__.py
's in the subfolders "PhotonDesignLib" & "proprietary" both cause all files in the subfolders to imported, so, for example, scriptfile.py
would access my proprietary files as so: import pyFIMM.proprietary.University
. This is accomplished via this hint, coded as follows in proprietary/__init__.py
:
import os, glob
__all__ = [ os.path.basename(f)[:-3] for f in glob.glob(os.path.dirname(__file__)+"/*.py")]
(Numerous coders from a few different institutions will have their own proprietary code, so we can share the base code but keep our proprietary files/functions to ourselves this way, without having to change any base code/import statements. I now realize that, for the more static PhotonDesignLib
folder, this is overkill.)
The file __globals.py
creates the object I need to use to communicate with their commercial app, with this code (this is all the code in this file):
import PhotonDesignLib.pdPythonLib as pd # the commercial lib/object
global fimm
fimm = pd.pdApp() # <- - this is the offending global object
All of my sub-modules contain a from __global import *
statement, and are able to access the object fimm
without specifically declaring it as a global
var, without any issue.
So I run scriptfile.py
, which has an import statement like from pyFIMM import *
.
Most importantly, scriptfile.py
initiates the TCP connection made to the application via fimm.connect()
right at the top, before issuing any commands that require the communication, and all the other modules call fimm.Exec(<commands for app>)
in various routines, which has been working swimmingly well - the fimm
object has so-far been accessible to all modules, and keeps it's connection state without issue.
The issue I am running into is that the file proprietary/University.py
can only successfully use the fimm
object when it's placed in the pyFIMM root-level directory (ie. the same folder as __globals.py
etc.). But when University.py
is imported from within the proprietary
sub-folder, it gives me an "application not initialized" error when I use the fimm
object, as if the object had been overwritten or re-initialized or something. The object still exists, it just isn't maintaining it's connection state when called by this sub-module. (I've checked that it's not reinitialized in another module.)
If, after the script fails in proprietary/University.py
, I use the console to send a command eg. pyFimm.fimm.Exec(<command to app>)
, it communicates just fine!
I set proprietary/University.py
to print a dir(fimm)
as a test right at the beginning, which works fine and looks like the fimm
object exists as expected, but a subsequent call in the same file to fimm.Exec()
indicates that the object's state is not correct, returning the "application not initialized" error.
This almost looks like there are two fimm
objects - one that the main python console (and pyFIMM modules) see, which works great, and another that proprietary/University.py
sees which doesn't know that we called fimm.connect()
already. Again, if I put University.py
in the main module folder "pyFIMM" it works fine - the fimm.Exec()
calls operate as expected!
FYI proprietary/University.py
imports the __globals.py
file as so:
import sys, os, inspect
ScriptDir = inspect.currentframe().f_code.co_filename # get path to this module file
(ParentDir , tail) = os.path.split(ScriptDir) # split off top-level directory from path
(ParentDir , tail) = os.path.split(ParentDir) # split off top-level directory from path
sys.path.append(ParentDir) # add ParentDir to the python search path
from __globals import * # import global vars & FimmWave connection object
global fimm # This line makes no difference, was just trying it.
(FYI, Somewhere on SO it was stated that inspect
was better than __file__
, hence the code above.)
Why do you think having the sub-module in a sub-folder causes the object to lose it's state?
I suspect the issue is either the way I instruct University.py
to import __globals.py
or the "import all files in this folder" method I used in proprietary/__init__.py
. But I have little idea how to fix it!
Thank you for looking at this question, and thanks in advance for your insightful comments.