(There are many similar and more generic questions, been trying the solutions from them after reading through them, can't get them working so asking here as a more situation-specific version of what I'm seeing)
I think I am really miss-understanding how Python does OOP due to my more C#/C++ background. So here's what I'm trying to do right this moment.
I'm starting with two modules to set up the rest of my project, partially as a sanity-check and proof-of-concept. One module logs things to a file as I go while also storing data from multiple modules (to eventually package them all and dump them on request) Doing all this in PyCharm and mentioning the error warnings it suggests by the way, and using Python 2.7
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter():
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__builtin__.mylogger = LogHelpers
Module 2:
src\ULTs\myULTs.py
mylogger.myLog.classEnter()
(both the modules and the root src\ have an empty init.py file in them)
So according to the totally awesome response here ( Python - Visibility of global variables in imported modules ) at this stage this should be working, but 'mylogger' becomes an 'unresolved reference'
So that was one approach. I also tried the more straight forward global one ( Python: How to make a cross-module variable? )
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
mylogger.myLog.classEnter()
This version gets a "parameter 'self' unfilled" error on the classEnter, which various reports seem to indicate means that mylogger is un-initialized (misleading error code but that's what it seems to mean)
And then I tried this..
Module 1:
src\helpers\logHelpers.py
class LogHelpers:
class log:
def classEnter(self):
#doing stuff
def __init__(self):
self.myLog = LogHelpers.log() #forgot to mention this was here initially
[..] various logging functions and variables to summarize what's happening
__mylogger = LogHelpers
__init__.py
__all__ = ['LogHelpers', hexlogger]
from .logHelpers import *
Module 2:
src\ULTs\myULTs.py
from helpers import mylogger
def someFunction(self):
global mylogger
mylogger.myLog.classEnter()
And this version gets the 'Global variable is undefined at the module level' error when I hover of global mylogger.
Then there is the idea of each other module tracking its own instance of a class apparently, if I end up having to I can go with that method and coordinate them.. but that's kind of a hack considering what I'm trying to do.
That's kind of where I'm at, that's the gist of what I'm trying to do... I'm reading through as many similar questions as I can but all of them seem to come back to these kinda of solutions (which don't seem to be working) or saying 'don't do that' (which is generally good advice but I'm not really grocking the preferred Pythony way of keeping multiple ongoing non-static classes organized for a large project - other than shoving them all in one directory)
Thoughts? (How badly am I mangling Python here?)
[EDIT] Based on feedback tried a mini version that eliminated the inner classes completely: Ok, so did a local mini-class based on what you said:
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self):
self.testVar += 1
myClass = testClass()
Set it up via init.py
__all__ = [myClass]
from .logHelpers import myClass
Went to other module and
from helpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar()
Ran it directly instead of looking at PyCharm, no Global anything.. NameError: name 'myClass is not defined
So still at square one :( (and still need to store state)
[EDIT] Adding Traceback:
Traceback (most recent call last):
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module> module = loadSource(a[0])
File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource module = imp.load_source(moduleName, fileName)
File "C:\[...mylocation...]\py\src\ULTs\LogHelpers_ULT.py", line 3, in <module> from helpers import myClass
File "C:\[...mylocation...]\py\src\helpers\__init__.py", line 7, in <module>
__all__ = [myClass]
NameError: name 'myClass' is not defined
============================================================================
kk, I got it working with the miniclass. I don't know why the other approach / approaches was not working, but this seemed to fix things. (Resources: http://docs.python-guide.org/en/latest/writing/structure/ , http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html )
**logHelpers.py**
[... some static logging functionality ...]
class testClass:
def __init__(self):
self.testVar = 2
def incrementVar(self, source):
self.testVar += 1
mylogger.myLog.info(source + " called, new val: " + str(self.testVar))
myClass = testClass()
**test_LogHelpers_ULT.py**
import unittest
from helpers.logHelpers import myClass
class Test_LogHelpers(unittest.TestCase):
def test_mini(self):
myClass.incrementVar("LogHelpers")
For some reason skipping the init.py (and leaving it blank) and going for the explicit importation worked. It also maintained state - I created a duplicate of the test file and my log output correctly had '3' for the first file to call the helper, and '4' for the second file to call the helper.
Thanks Daniel Roseman for the help and suggestions, they had me look a bit more in the right direction. If you can spot why the previous stuff wasn't working it would be much appreciate just to add to my understanding of this language, but I'm gonna go ahead and mark your answer as 'Answered' since it had some very useful feedback.