0

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.

Community
  • 1
  • 1
Demis
  • 5,278
  • 4
  • 23
  • 34
  • 1
    I suspect you are running into the problem describe [here](http://stackoverflow.com/questions/4798589/what-could-cause-a-python-module-to-be-imported-twice): `__global` is being imported twice via two different paths, because you're adding its directly explcitly to the path. The import code you show is extremely baroque. Why are you doing those `sys.path` manipulations? If `university` is within the enclosing `pyFIMM` package, it should just import `globals` via a relative import like `from ..__globals import *`. – BrenBarn Jan 15 '15 at 19:34
  • I did not know you could do relative imports like that in Py2.7! I shall try it now... – Demis Jan 15 '15 at 19:47
  • Your solution works very well! Also your comment on importing from two different paths is great - that certainly didn't occur to me. If you post that as an answer I'll gladly accept it. As to why I was using the archaic `sys.path` manipulations, it seems the `..__mod` technique you show [wasn't available a few years ago](http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python), so I've been using the baroque method for years. I humbly bow in honor of your python prowess! 8 hours of frustration concluded within 10 minutes of posting on SO... amazing. – Demis Jan 15 '15 at 20:00

0 Answers0