Sorry novice beginner programmers question about having only one instance of a class run at one time; and now struggling to find right way to structure the code.
I've researched but struggling to find the right approach, but lots of argument as to the right pythonic approach be that modules or Singltons e.g. Ensure that only one instance of a class gets run
I have some code (python 2.7.2) that continually logs 3 variables (2 temperatures and a pressure sensor) and then based on some logic looking at trends in the variables, moves a valve (if statements that if true, call defs in the module with lots of globals scattered around as I actually want all my defs to look at the same datasets and move the same valve). At the minute this all works fine in a module file.
However, so others in the lab can run my code, it needs to be launched from a general GUI and therefore my code needs to be threaded so that the process doesn’t tie up the GUI and command line.
I'd started to re-write the code into a Class (with threading superclass), and wanted to add some logic to that only one instance of the Class was called, so that >1 thread isn’t trying to control the same valve.
Now, I've discovered that this isn’t so easy in python and read that the notion of 'Singletons' are bad, and am struggling to find a solution on how to structure my code.
I would be grateful if someone could point me in the right direction, as I guess this must have been answered.
you should initalize one instance and access only your initialized constant
and for safety, raise exception in case someone tries to create another instance
class Singletone(object):
__initialized = False
def __init__(self):
if Singletone.__initialized:
raise Exception("You can't create more than 1 instance of Singletone")
Singletone.__initialized = True
MY_SINGLETONE_INSTANCE = Singletone()
From http://norvig.com/python-iaq.html:
def singleton(object, instantiated=[]):
"Raise an exception if an object of this class has been instantiated before."
assert object.__class__ not in instantiated, \
"%s is a Singleton class but is already instantiated" % object.__class__
instantiated.append(object.__class__)
class YourClass:
"A singleton class to do something ..."
def __init__(self, args):
singleton(self)
...
Not sure how you'd have to adapt that for multithreaded applications, though.
Related
I have a main python process which runs another python process. I want to patch or set some attribute of the child process so that it uses only what I set for it rather than what's defined in it.
To elucidate: child process has a function foo() but i want to change it to foobar() in my parent so that when foo gets 'called' it executes 'foobar' instead.
I'm pretty sure this is called monkey-patching from what i have learnt but i dont know what others refer to it as
This is mainly for testing the code I developed
I tried using preexec_fn in Popen() to change the function entirely
In my child process:
def foo():
"do this"
In my parent:
def foobar():
print "do this instead"
def pre_exec():
import child
setattr(child, 'foo', foobar)
Popen(['python', 'child.py'],preexec_fn=pre_exec)
I expected it to print "do this instead" but the actual output was "do this".
Any help or idea is appreciated!
Just a note, but monkey patching makes debugging awful. While it was a common practice in Ruby, it's always been frowned upon in python. If you absolutely have to do it, you need to mark out whatever you're doing in a huge comment explaining why you couldn't do without it to whoever inherits your code.
So, if you want a child process to do something different than the main one, the most appropriate thing to do is to pass it an argument.
When you call the child, it should passed an argument to let it know to swap out the function.
Popen(['python', 'child.py', '--use-alternate-function'])
edit: the pre exec function is a function called after your program forks ( makes a copy of itself in memory ) and before the child copy calls exec ( which swaps it out for a new fresh copy of the program name you gave it ). It's for setting environment variables or whatever in a single threaded environment. I've never needed to touch it in years of using python.
This seems to be a common error in Python, and I've found many instances of people asking about similar but spent the last (long amount of time) trying those solutions where they seemed applicable and have had no luck, so resorting to asking to find out what I'm missing.
I'm receiving AttributeError: WebHandler instance has no attribute 'search_str'
It seems to be this one particular method, any time I call any of the class variables set in ___init___ from this method I receive this error. I've extracted it to a test file as a simple function rather than a class method and it works fine, and I've tried re-indenting everything a few times to make sure it wasn't that, so I'm at a loss on this.
I'm using Python 2.7 and TextWrangler if either of these are helpful (TextWrangler hasn't given me any problems in 3 years like this, but figured anything should be included)
import requests
import re
class WebHandler():
def ___init___(self):
self.urllist = []
self.search_str = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.I|re.M)
def set_urls(self, test, data):
for line in test[11:]:
if (("even" in line) or ("odd" in line)):
match = re.search(self.search_str, line)
self.urllist.append(match.group(0))
Another thing I tried, if I copy the attributes from ___init___ and simply make them local to set_urls() and call them without self that way it works properly and doesn't throw any errors, which is confusing me even more.
No idea what I'm missing. Thanks!
Your init function has three underscores:
def ___init___(self):
It should have only two:
def __init__(self):
As it is written now, it is not being called when you create a new object.
This that you have:
def ___init___(self):
Is not the same as this that gets called when an object is instantiated:
def __init__(self):
The difference is that you have three underscores on either side of init, while two are required.
I would like to handle a NameError exception by injecting the desired missing variable into the frame and then continue the execution from last attempted instruction.
The following pseudo-code should illustrate my needs.
def function():
return missing_var
try:
print function()
except NameError:
frame = inspect.trace()[-1][0]
# inject missing variable
frame.f_globals["missing_var"] = ...
# continue frame execution from last attempted instruction
exec frame.f_code from frame.f_lasti
Read the whole unittest on repl.it
Notes
As pointed out by ivan_pozdeev in his answer, this is known as resumption.
After more research, I found Veedrac's answer to the question Resuming program at line number in the context before an exception using a custom sys.excepthook posted by lc2817 very interesting. It relies on Richie Hindle's work.
Background
The code runs in a slave process, which is controlled by a parent. Tasks (functions really) are written in the parent and latter passed to the slave using dill. I expect some tasks (running in the slave process) to try to access variables from outer scopes in the parent and I'd like the slave to request those variables to the parent on the fly.
p.s.: I don't expect this magic to run in a production environment.
On the contrary to what various commenters are saying, "resume-on-error" exception handling is possible in Python. The library fuckit.py implements said strategy. It steamrollers errors by rewriting the source code of your module at import time, inserting try...except blocks around every statement and swallowing all exceptions. So perhaps you could try a similar sort of tactic?
It goes without saying: that library is intended as a joke. Don't ever use it in production code.
You mentioned that your use case is to trap references to missing names. Have you thought about using metaprogramming to run your code in the context of a "smart" namespace such as a defaultdict? (This is perhaps only marginally less of a bad idea than fuckit.py.)
from collections import defaultdict
class NoMissingNamesMeta(type):
#classmethod
def __prepare__(meta, name, bases):
return defaultdict(lambda: "foo")
class MyClass(metaclass=NoMissingNamesMeta):
x = y + "bar" # y doesn't exist
>>> MyClass.x
'foobar'
NoMissingNamesMeta is a metaclass - a language construct for customising the behaviour of the class statement. Here we're using the __prepare__ method to customise the dictionary which will be used as the class's namespace during creation of the class. Thus, because we're using a defaultdict instead of a regular dictionary, a class whose metaclass is NoMissingNamesMeta will never get a NameError. Any names referred to during the creation of the class will be auto-initialised to "foo".
This approach is similar to #AndréFratelli's idea of manually requesting the lazily-initialised data from a Scope object. In production I'd do that, not this. The metaclass version requires less typing to write the client code, but at the expense of a lot more magic. (Imagine yourself debugging this code in two years, trying to understand why non-existent variables are dynamically being brought into scope!)
The "resumption" exception handling technique has proven to be problematic, that's why it's missing from C++ and later languages.
Your best bet is to use a while loop to not resume where the exception was thrown but rather repeat from a predetermined place:
while True:
try:
do_something()
except NameError as e:
handle_error()
else:
break
You really can't unwind the stack after an exception is thrown, so you'd have to deal with the issue before hand. If your requirement is to generate these variables on the fly (which wouldn't be recommended, but you seem to understand that), then you'd have to actually request them. You can implement a mechanism for that (such as having a global custom Scope class instance and overriding __getitem__, or using something like the __dir__ function), but not as you are asking for it.
I just realized there is something mysterious (at least for me) in the way you can add vertex instructions in Kivy with the with Python statement. For example, the way with is used goes something like this:
... some code
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas:
Rectangle(pos=self.pos, size=self.size)
At the beginning I thought that it was just the with Python statement that I have used occasionally. But suddenly I realize it is not. Usually it looks more like this (example taken from here):
with open('output.txt', 'w') as f:
f.write('Hi there!')
There is usually an as after the instance and something like and alias to the object. In the Kivy example we don't define and alias which is still ok. But the part that puzzles me is that instruction Rectangle is still associated to the self.canvas. After reading about the with statement, I am quite convinced that the Kivy code should be written like:
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas as c:
c.add (Rectangle(pos=self.pos, size=self.size))
I am assuming that internally the method add is the one being called. The assumption is based that we can simply add the rectangles with self.add (Rectangle(pos=self.pos, size=self.size))
Am I missing something about the with Python statement? or is this somehow something Kivy implements?
I don't know Kivy, but I think I can guess how this specific construction work.
Instead of keeping a handle to the object you are interacting with (the canvas?), the with statement is programmed to store it in some global variable, hidden to you. Then, the statements you use inside with use that global variable to retrieve the object. At the end of the block, the global variable is cleared as part of cleanup.
The result is a trade-off: code is less explicit (which is usually a desired feature in Python). However, the code is shorter, which might lead to easier understanding (with the assumption that the reader knows how Kivy works). This is actually one of the techniques of making embedded DSLs in Python.
There are some technicalities involved. For example, if you want to be able to nest such constructions (put one with inside another), instead of a simple global variable you would want to use a global variable that keeps a stack of such objects. Also, if you need to deal with threading, you would use a thread-local variable instead of a global one. But the generic mechanism is still the same—Kivy uses some state which is kept in a place outside your direct control.
There is nothing extra magical with the with statement, but perhaps you are unaware of how it works?
In order for any object to be used in a with statement it must implement two methods: __enter__ and __exit__. __enter__ is called when the with block is entered, and __exit__ is called when the block is exited for any reason.
What the object does in its __enter__ method is, of course, up to it. Since I don't have the Kivy code I can only guess that its canvas.__enter__ method sets a global variable somewhere, and that Rectangle checks that global to see where it should be drawing.
I just realized there is something mysterious (at least for me) in the way you can add vertex instructions in Kivy with the with Python statement. For example, the way with is used goes something like this:
... some code
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas:
Rectangle(pos=self.pos, size=self.size)
At the beginning I thought that it was just the with Python statement that I have used occasionally. But suddenly I realize it is not. Usually it looks more like this (example taken from here):
with open('output.txt', 'w') as f:
f.write('Hi there!')
There is usually an as after the instance and something like and alias to the object. In the Kivy example we don't define and alias which is still ok. But the part that puzzles me is that instruction Rectangle is still associated to the self.canvas. After reading about the with statement, I am quite convinced that the Kivy code should be written like:
class MyWidget(Widget)
... some code
def some_method (self):
with self.canvas as c:
c.add (Rectangle(pos=self.pos, size=self.size))
I am assuming that internally the method add is the one being called. The assumption is based that we can simply add the rectangles with self.add (Rectangle(pos=self.pos, size=self.size))
Am I missing something about the with Python statement? or is this somehow something Kivy implements?
I don't know Kivy, but I think I can guess how this specific construction work.
Instead of keeping a handle to the object you are interacting with (the canvas?), the with statement is programmed to store it in some global variable, hidden to you. Then, the statements you use inside with use that global variable to retrieve the object. At the end of the block, the global variable is cleared as part of cleanup.
The result is a trade-off: code is less explicit (which is usually a desired feature in Python). However, the code is shorter, which might lead to easier understanding (with the assumption that the reader knows how Kivy works). This is actually one of the techniques of making embedded DSLs in Python.
There are some technicalities involved. For example, if you want to be able to nest such constructions (put one with inside another), instead of a simple global variable you would want to use a global variable that keeps a stack of such objects. Also, if you need to deal with threading, you would use a thread-local variable instead of a global one. But the generic mechanism is still the same—Kivy uses some state which is kept in a place outside your direct control.
There is nothing extra magical with the with statement, but perhaps you are unaware of how it works?
In order for any object to be used in a with statement it must implement two methods: __enter__ and __exit__. __enter__ is called when the with block is entered, and __exit__ is called when the block is exited for any reason.
What the object does in its __enter__ method is, of course, up to it. Since I don't have the Kivy code I can only guess that its canvas.__enter__ method sets a global variable somewhere, and that Rectangle checks that global to see where it should be drawing.