Attempt to call an undefined function glDetachShader - pyopengl

In my python code, I have these lines:
def __del__(self):
for shader in self.shaders:
GL.glDetachShader(self.program, shader)
GL.glDeleteShader(shader)
GL.glDeleteProgram(self.program)
But when the code executes these lines, I end up seeing this problem:
Exception ignored in: <bound method Shader.__del__ of <__main__.Shader object at 0x0000016E4AFFE550>>
Traceback (most recent call last):
File "C:\Germano\Dev\Gartic\tests\modernOpenGL2.py", line 214, in __del__
GL.glDetachShader(self.program, shader)
File "C:\Users\Germano\AppData\Local\Programs\Python\Python36\lib\site-packages\OpenGL\platform\baseplatform.py", line 407, in __call__
self.__name__, self.__name__,
OpenGL.error.NullFunctionError: Attempt to call an undefined function glDetachShader, check for bool(glDetachShader) before calling
What is going on? How can I fix this problem??

__del__ is likely only being called after the OpenGL context is being destroyed, leading to the NullFunctionError. If the Program/Shader class is surviving until the end of the lifetime of the application after the window is destroyed, when the Python interpreter is calling all of your custom delete functions, all gl* function calls would basically not be available. You can rely on context destruction to delete all OpenGL-associated objects in this case.
However, it is still a good idea to free up memory when you are no longer using a shader/program object during the lifetime of your application, when the context still exists (see this answer for more info)! I personally also ran into a similar issue myself when deleting textures or buffers. I would recommend wrapping your code in a try/except block, so it would look like this:
def __del__(self):
try:
#if the context is alive, you want to try and delete shader/program stuff manually
#this could be triggered with e.g. `del my_awesome_program_class_object`
for shader in self.shaders:
GL.glDetachShader(self.program, shader)
GL.glDeleteShader(shader)
GL.glDeleteProgram(self.program)
except OpenGL.error.NullFunctionError as error:
pass#do nothing; context already deleted my shader/program stuff!
Hope this explanation makes things clearer, as those NullFunctionErrors are definitely tricky to understand without knowing why they are occurring in the first place!

Related

Wrap every function of every class of a module

Objective
Wrap every function of every class of gspread module.
I know there are countless of posts on the subject and most unanimously instruct to use decorators.
I'm not too familiar with decorators and felt like that approach is not as seamless as I hoped for. perhaps I didn't understand correctly.
But, I found this answer which "felt" like what I'm looking for.
(poor) Attempt
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import os
import inspect
class GoogleSheetAPI:
def __init__(self):
f = os.path.join(os.path.dirname(__file__), 'credentials.json')
os.environ.setdefault('GOOGLE_APPLICATION_CREDENTIALS', f)
scope = ['https://spreadsheets.google.com/feeds',
'https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name(f, scope)
self.client = gspread.authorize(credentials)
self.client.login()
def SafeCall(f):
try:
print 'before call'
f()
print 'after call'
except:
print 'exception caught'
return None
for class_name, c in inspect.getmembers(gspread, inspect.isclass):
for method_name, f in inspect.getmembers(c, inspect.ismethod):
setattr(c, f, SafeCall(f)) # TypeError: attribute name must be string, not 'instancemethod'
g = GoogleSheetAPI()
spreadsheet = g.client.open_by_key('<ID>') # calls a function in gspread.Client
worksheet = spreadsheet.get_worksheet(0) # calls a function in gspread.Spreadsheet
worksheet.add_rows(['key','value']) # calls a function in gspread.Worksheet
Notes
When I use the word "seamless" I mean that considering my code has many calls to many gspread functions, I want to change as little as possible. Using inspect/setattr seems like the perfect/seamless trick.
There are three obvious issues with your code actually.
The first one is the TypeError - which is easy to solve FWIW: as the error message (raised by setattr() states, "attribute name must be string, not 'instancemethod'". And you're indeed trying to use f (the method itself) instead of method_name. What you want here is of course:
setattr(c, method_name, SafeCall(f))
The second issue is that your SafeCall "decorator" is NOT a decorator. A decorator (well, the kind of decorator you want here at least) returns a function that wraps the original one, your current implementation just calls the original function. Actually, it is almost what SafeCall should actually return. An example of a proper decorator would be:
def decorator(func):
def wrapper(*args, **kw):
print("before calling {}".format(func))
result = func(*args, **kw)
print("after calling {}".format(func))
return result
return wrapper
And finally, the third obvious issue is here:
except:
print 'exception caught'
return None
You certainly don't want this. This
1/ will catch absolutely everything (incuding SysExit, which is what Python raises on sys.exit() calls and StopIteration which is how iterators signals they are exhausted),
2/ discard all the very useful debugging infos - making it impossible to diagnose what actuall went wrong
3/ return something that can be plain unusable so you'll have to test the return value of each method call, and since you won't know what went wrong, you won't be able to handle the issue otherwise than printing "oops, something went wrong but don't ask me what nor where nor why" and exiting the program, which is definitly not better than letting the exception propagate - the program will crash in both cases, but at least if you leave the exception alone you'll have some hints on what caused the issue.
4/ or, much worse, return a valid return value for the method (yes, quite a few method are designed to change state and return None) so you won't even know something went wrong and happily continue execution - which is a sure way to have incorrect result and corrupted data.
5/ not to mention that the methods you're decorating that way are very probably calling each others and using (expected) exceptions internally (with proper exception handling), so you are actually introducing bugs in an otherwise working (or mostly working) library.
IOW, this is probably the worse antipattern you can ever think of...

Python Error message customization [duplicate]

When I raise my owns exceptions in my Python libraries, the exception stack shows the raise-line itself as the last item of the stack. This is obviously not an error, is conceptually right, but points the focus on something that is not useful for debugging when you're are using code externally, for example as a module.
Is there a way to avoid this and force Python to show the previous-to-last stack item as the last one, like the standard Python libraries.
Due warning: modifying the behaviour of the interpreter is generally frowned upon. And in any case, seeing exactly where an error was raised may be helpful in debugging, especially if a function can raise an error for several different reasons.
If you use the traceback module, and replace sys.excepthook with a custom function, it's probably possible to do this. But making the change will affect error display for the entire program, not just your module, so is probably not recommended.
You could also look at putting code in try/except blocks, then modifying the error and re-raising it. But your time is probably better spent making unexpected errors unlikely, and writing informative error messages for those that could arise.
you can create your own exception hook in python. below is the example of code that i am using.
import sys
import traceback
def exceptionHandler(got_exception_type, got_exception, got_traceback):
listing = traceback.format_exception(got_exception_type, got_exception, got_traceback)
# Removing the listing of statement raise (raise line).
del listing[-2]
filelist = ["org.python.pydev"] # avoiding the debuger modules.
listing = [ item for item in listing if len([f for f in filelist if f in item]) == 0 ]
files = [line for line in listing if line.startswith(" File")]
if len(files) == 1:
# only one file, remove the header.
del listing[0]
print>>sys.stderr, "".join(listing)
And below are some lines that I have used in my custom exception code.
sys.excepthook = exceptionHandler
raise Exception("My Custom error message.")
In the method exception you can add file names or module names in list "filenames" if you want to ignore any unwanted files. As I have ignored the python pydev module since I am using pydev debugger in eclipse.
The above is used in my own module for a specific purpose. you can modify and use it for your modules.
I'd suggest to not use the Exception mechanism to validate arguments, as tempting as that is. Coding with exceptions as conditionals is like saying, "crash my app if, as a developer, I don't think of all the bad conditions my provided arguments can cause. Perhaps using exceptions for things not only out of your control but also which is under control of something else like the OS or hardware or the Python language would be more logical, I don't know. In practice however I use exceptions as you request a solution for.
To answer your question, in part, it is just as simple to code thusly:
class MyObject(object):
def saveas(self, filename):
if not validate_filename(filename):
return False
...
caller
if not myobject.saveas(filename): report_and_retry()
Perhaps not a great answer, just something to think about.

Tkinter Text and Itemconfigure Memory Leak

Background:
A few months ago, I posted here asking about a memory leak occurring in my Tkinter canvas class. The primary cause of this was an accidental loop over several key bindings, and the removal of these bindings largely alleviated my problem. However, there remained a small memory leak, but I disregarded it as negligible enough to ignore. At this point (after a couple more months of work), the previously small leak has grown to be potentially damaging -- after an hour of continuous use my program can now fill 800mb+ of system memory, which is a serious concern as without the leak, the program should only require ~60mb.
The Issue:
After some testing, I have narrowed the origin down to two causes:
1. Tkinter itemconfigure function
2. Tkinter text objects
The code snippet below recreates the issue on my machine.
from Tkinter import *
stop=0
class Interface:
def Initialise(self,master):
global x
self.master=master
x=50
width,height=master.winfo_screenwidth(),master.winfo_screenheight()
self.c=Canvas(self.master, width=width, height=height, bg='white',scrollregion=(-1500,-1500,10000,10000))
self.c.pack(side=LEFT,expand=True,fill=BOTH)
self.Regenerate()
self.master.bind("<a>", self.auto)
def Regenerate(self):
self.G=UI_Canvas()
self.G.Visualise(self.c,x)
def auto(self, event):
global stop
stop+=1
self.master.after(5, self.auto_rotate)
def auto_rotate(self):
global x
if stop % 2 == 1:
x+=0.1
self.Regenerate()
self.c.after(5, self.auto_rotate)
class UI_Canvas:
def Visualise(self, canvas,x):
self.canvas=canvas
self.canvas.delete('Network')
data=[((x,400,0),1),((x,450,0),2),((x+50,450,0),3),((x+50,400,0),4)]
for (x,y,z), j in data:
self.canvas.create_oval(x-5, y-5, x+5, y+5, fill='gray15', tags=(j,("Node %.5s" % j),'Network'))
#self.canvas.create_text(x-10,y, text=(j), fill='black', font=('Helvetica',12), tags=(j, ("Node %.5s" % j), 'Network'))
root=Tk()
UI=Interface()
UI.Initialise(root)
root.mainloop()
By commenting out all text and itemconfigure objects, the leak disappears and the program runs at a constant memory usage (as required). Specifically, commenting out all text objects (leaving no objects to be configured), removes the leak, and it therefore seems to me that the repeated refresh of text on-screen is causing the leak. Other canvas objects (lines, ovals and polygons) that I use do not cause this issue.
Attempted Solutions
Other memory leak problems posted here seem to revolve around having updates within loops, but I have not relied on this method, and instead delete then re-create objects inside a loop. As previously mentioned, this method works fine with shapes, but apparently not with text. I have moved the text object code into my 'master' canvas class (thereby no longer being directly in a refresh loop), and instead attempted to configure it from the loop, but the issue persists.
Question
The information contained in these text objects is very important to easily using my program, and resolving this issue is essential. My questions are: what is causing this issue? And are there any possible solutions?
Thank you in advance for any assistance!

Implementing my own Lens in Panda3D

Background
I'm trying to implement a highly non-linear lens to do lens distortion in Panda3D for a complex projection setup. I want to use this implementation following this approach.
The question
Can I do it in Python (and if so, how, what am I doing wrong) or do I have to do it in C++ (and if so, where do I start)?
Attempts so far
I've tried subclassing Lens, but if I let my subclass call the super constructor (or don't override the constructor at all), I get an error:
>>> from panda3d.core import Lens
>>> class MyLens(Lens):
... def __init__(self):
... super(MyLens,self).__init__()
...
>>> l = MyLens()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __init__
TypeError: Error Can Not Init Constant Class (Lens)
If I don't call the super constructor, the class isinstance(Lens), but not recognized as such by Panda3D code:
fcamNode = Camera('fcam')
flens = MyLens.MyLens()
assert isinstance(flens, Lens)
fcamNode.setLens(flens)
results in TypeError: LensNode.set_lens() argument 1 must be Lens, not MyLens.
If I subclass PerspectiveLens instead, I can call the super constructor and pass instances of my class to setLens(), but none of its overridden methods are ever called and the rendered scene looks like it was rendered with the stock PerspectiveLens.
That is all coded in C++, i.e. the Lens class is internally a C++ class and all the other classes are also C++ classes which overload the C++ Lens class.
If you overload such Python-wrapped class and pass that object down to some C++ code again, the C++ code wont recognize the Python overwriting.
You might be able to write a C++ Lens superclass which is able to do that, i.e. which implements all possible virtual functions and in all cases, always looks up wether there is a related Python object attribute which can be called. Note that this is likely to be slow.
In C++, you find the definition of Lens here and here.
Take a look at the FisheyeLens here to see what functions you have to overwrite from Lens.

Segmentation Fault when wrapping V8 in a class?

I want to use Google's Javascript Engine V8 in a project, and attempted to write a wrapper class for the engine. Parts of the Code are copied from samples/shell.cc, from the V8 Distribution.
However, it just aborts with a Segmentation fault, and I can't figure out why, although the problem is happening around v8::internal::Top::global_context() (due to an invalid context, which appears to be NULL).. The code itself looks fine to me, but maybe I did something incredibly stupid :-).
The Segmentation fault in my Code happens in v8::Script::Compile.
Code in Question (Updated): https://gist.github.com/4c28227185a14bb6288c
Thanks to Luis G. Costantini R.'s Answer, there is no longer a problem in Set (It doesn't abort anymore), however, exposed names are still not available and will result in a ReferenceError...
Thy to change v8::Context::Scope context_scope(context); from the constructor (line 134) to internal_executeString (before script = v8::Script::Compile(source, name);). That because the destructor of the class v8::Context::Scope exits from the context.
I changed the method addFunction:
void addFunction(const std::string& fname, v8::InvocationCallback func)
{
v8::HandleScope handle_scope;
std::cout << "before ::Set()" << std::endl;
v8::Context::Scope context_scope(context);
context->Global()->Set(v8::String::New(fname.c_str()),
v8::FunctionTemplate::New(func)->GetFunction());
std::cout << "after ::Set()" << std::endl;
}
The function must be added to the global object of the context used to execute the script. There is an excellent tutorial (in two parts) of V8:
http://www.homepluspower.info/2010/06/v8-javascript-engine-tutorial-part-1.html
and
http://www.homepluspower.info/2010/06/v8-javascript-engine-tutorial-part-2.html
If you try to create an instance of JavaScript Function (FunctionTemplate::GetFunction()) or JavaScript Object (ObjectTemplate::NewInstance()) before entering the context (via Context::Scope), you get the segmentation fault. The reason: there is no JavaScript context available and both Function and Object always exist in a JavaScript execution context only. As per V8 documentation:
Function:
A JavaScript function object (ECMA-262, 15.3).
Object:
A JavaScript object (ECMA-262, 4.3.3).
The stack backtrace is almost useless unless I download all the source and try to build it myself, so... :)
Change js.executeString("1+1", true, false); to js.executeString("1+1", true, true); and see what the exception handler tells you?
Looks like you just got stung by this bug, that is if you have not already taken note of it. Perhaps submit another report since the referenced one looks old. Perhaps dig a little deeper and investigate the stack frame at every function call until the Segmentation Fault is received, you could either find a work around or the fix for this bug :)
I had a similar segmentation fault and the problem turned out to be the following. I was creating a new thread and attempting to create an object template and object in that thread. Unfortunately it seems that if you create a thread, you need to make sure that you enter a v8::Context again in order to do such things.
I got it working by passing a Handle to the v8::Context::Calling to the newly created thread and entered it in the new thread by using a scope.
I wrote this here as it is the only useful thing that comes up when I do a google search for the segmentation fault.