Reputation: 1047
I have a program which imports two modules, one we will call operations
(which is just a series of functions) and the other we call tracking
(which is a class). The program tracking
module monitors a series of messages, has some error state flags, and so forth. The program sorts information in tracking
by severity and relevant parties, then dumps this to different files at the end.
I create a single instance of the tracking class with myTrack = tracking.Tracking()
. (Yes, this is global state and therefore bad, but it is pretty handy)
Unforunately, I would like to use my tracking
object within the operations
module, just to track errors and warnings. It looks like I can pass myTrack
to functions in the operations
module as an argument, modifying each and every one of the functions.
However, is there a "better" or "more Pythonic" way to do this? I suspect there is something with namespaces which I have failed to grasp.
Upvotes: 2
Views: 226
Reputation: 26586
I am not sure I understand your problem correctly, but I think you are looking for a way to make the functions in one module automatically aware of the state an object in another module without explicitly passing that object every time you call a function.
The basic problem is that at some level you have to pass the object and have it available to all the functions you need. Modules are simply not meant to work like that.
I think a better idea will be to define an Operations
class that contains all the functions you need as methods as well as holding an instance of Tracking
. You can just pass in your Tracking
object and create an Operations
instance, and use that to call whatever function that you need.
myTrack = tracking.Tracking()
myOperation=operations.Operations(myTrack)
myOperation.doSomething()
Upvotes: 3
Reputation: 41496
Your tracking
module (recording details about a series of events for later analysis or display) sounds suspiciously like the standard library's logging
module. So you may want to investigate that a little more closely.
If you decide to head down that path, then the operations
module would just log events to a specific logger (e.g. "myapp.operations"), your tracking
module would provide a logging handler that did what you wanted, and your main module would hook the two together (by registering the tracking handler with the "myapp.operations" logger).
You can also set up something like that yourself, but really, if you want to track events in a Python program... just use logging
.
Upvotes: 3
Reputation: 184191
There are a lot of ways you could refactor this, but one place you might start is to add a track()
function to your operations
module. Have it do nothing by default.
def track(message): # use the right signature though!
pass
In your operations
module you would then call your track()
function anywhere you might want to track something.
Assuming your Tracking
object has a method called track()
that does the actual tracking, then in your main module, you can do this:
myTrack = tracking.Tracking()
operations.track = myTrack.track
This replaces the module's (do-nothing) track
function with the method from your Tracking
instance.
Basically, you have provided a "hook" which anyone can use to add tracking to your operations
module, and then used that hook yourself.
Yes, this is more "global state," but it's module-global, which is not really global.
Upvotes: 4