python code runs in standalone function but not as part of class - python

In Python 3.3.5 I am building a class out of some code that works as standalone functions, but it aborts without an error message when the class version is run. It relies on a 3rd party package pcFastDB, distributed as a pyd.
unit1.py
import sys
import pcFastDB as p3
def get_context():
return p3.pcContext.create()
def get_DB(ctx, dbName):
return p3.pcDB.open(ctx, dbName)
.. more..
can be used as:
ctx = get_context()
db = get_DB(ctx, 'tester')
..do things with db
but
Unit2.py
import pcFastDB as p3
class DBOperation(object):
def __init__(self, DB_name):
'''
Get the context, open the database and fill a channel list
'''
self.ctx = p3.pcContext.create()
print('Context ' + str(self.ctx ))
print(' - opening ' + DB_name)
self.db = p3.pcDB.open(self.ctx, DB_name) #aborts here
print('DB opened successfully...' +str(self.db))
aborts silently when I try to open the DB.
db = DBOperation('tester')
The tester db exists and is in the project folder where I am running it.
There is no exception, no error, it just stops executing. PyDev doesn't like the pyd file very well. I don't get any code insight so debugging is kind of mysterious, but in IPython3 I can see all of the functions and class members, so I know its ok. Unfortunately debugging in IPython3 is an unfathomable mystery to me.
Anyway, I know that I am calling the right functions and I know the functions work, because it all works fine in Unit1, it just doesn't work as a class member. Is this even possible?
I've broken the DB lines out of the init and called them separately, and I've broken ctx out of the class and passed it into the functions but that doesn't work either. It behaves identically when run from within PyDev, IPython3 or the command line.
Any ideas?

Thanks everyone, I've gotten it working by basically rewriting the identical code into a new module. There seems to have been something weird with the file itself. I'm blaming PyDev.
Marc

Related

How do I start a COM server? Code is in Python

I want to run Python code as a COM server. Eventually I want to run an RTD server available here. But first I want to know what exactly you have to do to getting any COM server running. So let's focus on this example.
class HelloWorld:
_reg_clsid_ = "{7CC9F362-486D-11D1-BB48-0000E838A65F}"
_reg_desc_ = "Python Test COM Server"
_reg_progid_ = "Python.TestServer"
_public_methods_ = ['Hello']
_public_attrs_ = ['softspace', 'noCalls']
_readonly_attrs_ = ['noCalls']
def __init__(self):
self.softspace = 1
self.noCalls = 0
def Hello(self, who):
self.noCalls = self.noCalls + 1
# insert "softspace" number of spaces
return "Hello" + " " * self.softspace + who
if __name__=='__main__':
import win32com.server.register
win32com.server.register.UseCommandLine(HelloWorld)
Ok, this works in the way that there were no errors and server is registered, hence it is available in the HKEY_CLASSES_ROOT registry. But what can I do with this? Some say you have to compile a instance and have a .dll or .exe file. WHat else do I have to do?
Well, I ran your example. The registry key for the server is at:
HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{7CC9F362-486D-11D1-BB48-0000E838A65F}
It has two subkeys... one for LocalServer32 and one for InProcServer32
I created a simple VBA macro in Excel:
Sub d()
Set obj = CreateObject("Python.TestServer")
MsgBox obj.Hello("joe")
End Sub
Macro ran just fine. My version of Excel is 64-bit. I ran the macro and then fired up Task Manager while the message box was being displayed. I could see pythonw.exe running in the background.
The only difference between my python script and yours is probably the name and also that I added a line to print to make sure I was executing the function:
if __name__=='__main__':
import win32com.server.register
print("Going to register...")
win32com.server.register.UseCommandLine(HelloWorld)
When I ran the 64-bit csript.exe test, it worked... as expected... when I ran the 32-bit version it failed.
I know why...sort of...
The registry entry for InProcServer32 is pythoncom36.dll
That's no good. It is an incomplete path. I tried modifying the path variable on my shell to add to one of the 3 places where the DLL existed on my system, but it didn't work. Also, tried coding the path in the InProcServer32. That didn't work.. kept saying it couldn't find the file.
I ran procmon, and then I observerved that it couldn't load vcruntime140.dll. Found the directory under python where those files were, and added to my path. It got further along. If I cared enough, I might try more. Eventually using procmon, I could find all the problems. But you can do that.
My simple solution was to rename the key InProcServer32 for the CLSID to be _InProcServer32. How does that work? Well, the system can't find InProcServer32 so it always uses LocalServer32--for 32-bit and 64-bit processes. If you need the speed of in process then you'd need to fix the problem by using procmon and being relentless until you solved all the File Not Found errors and such. But, if you don't need the speed of in process, then just using the LocalServer32 might solve the problem.
Caveats I'm using an Anaconda distro that my employer limits access to and I can only install it from the employee store. YMMV.

How do you get a module to function, and be recognized from within Choreographe on a Nao robot?

I'm using a Nao robot, and the python SDK, and I'm trying to create my own module for it. Right now it is just a dummy module with one function: getJoke().
I have my file tellAJoke.py located under the path /home/nao/tellAJoke.py and I have updated the autoload.ini file to include the following:
[python]
/home/nao/tellAJoke.py
When I boot up the robot, it says what it normally does on startup, but also says what my getJoke() function returns, "This is a bad joke".
I'm not sure what I'm doing wrong here. When I ssh onto the robot, and run the code it runs just fine, but never when I want to import the module with ALProxy in Choreographe.
EDIT: I added the actual dummy code I have.
from naoqi import ALBroker
from naoqi import ALModule
from naoqi import ALProxy
import sys
class JokerModule(ALModule):
"""Tells you a random joke"""
def __init__(self, name):
print "WE HAVE INITED"
self.tts = ALProxy("ALTextToSpeech")
ALModule.__init__(self, name)
global memory
memory = ALProxy("ALMemory")
memory.subscribeToEvent("SayingJoke", "Joker", "getJoke")
def getJoke(self, *_args):
"""Returns a joke"""
self.tts.say("Joke time!")
def main():
"""main entry point"""
pip = '192.168.1.104'
pport = 9559
myBroker = ALBroker("myBroker", '0.0.0.0', 0, pip, pport)
global Joker
Joker = JokerModule("Joker")
speechProxy = ALProxy("ALTextToSpeech")
Joker.getJoke()
if __name__ == '__main__':
main()
Here is a guide on making services (a.k.a. "modules", but that term is confusing because it has another meaning in Python): http://doc.aldebaran.com/2-4/dev/libqi/guide/py-service.html (this doc is for NAOqi 2.4 but things should work mostly the same for 2.1, which is more often used on NAO)
But, you might want to try Robot Jumpstarter, that contains templates for various typical projects, including a python service (that works as explained in the document above).
clone it and run python jumpstart.py python-service tell-a-joke TellAJoke
... and it will generate a project that you can:
install on the robot witch Choregraphe
run in standalone with python tell-a-joke/app/scripts/tellajoke.py --qi-url your-naos-ip
... and in both cases you will be able to call it from from Choregraphe boxes etc.
(edit)
Now that you posted your code - in this specific case your problem is just that after Joker.getJoke(), your program reaches the end and terminates. The usual "modern" way of doing that would be with a qi.Application() that would .run() (all that is done in the jumpstarter template). You could do a while True: sleep(1) or something, which is not very pretty but would work (I recommend migrating to NAOqi 2, and instead of using ALProxy and ALBroker, use session.service and qi.Application ... the two are interoperable)

PyCharm for Python gives error for self is not defined

My code has the following
import mod_curves
import mod_dates
import datetime
import modcalinputs
curvesclass = mod_curves.curvecalcs()
datesclass = mod_dates.datecalcs()
calcInputs = modcalinputs.calcinputs()
1. List item
class payment_calculations:
def __init__(self):
self.__accrualdays = 0
self.__accrualrate = 0
self.__coupondates = {}
....
When I run the PyCharm over any of the variables including the self in the init declaration I see the following reported by PyCharm (NameError)name ´self´ is not defined. This error appears on every variable in my code that starts with self.__
This is blocking any debugging I can do.
However, when I execute my code the app functions as expected.
How can I get rid of that error message_
Seems to work for me, using PyCharm 4.5.3. Apologies if this is too obvious of an answer:
When debugging, you can only view contents of variables if the debugger is currently in a place where those variables are in scope.
For example, here I have set a breakpoint in main, where self and self.__x are not in scope.
Here, I have set a breakpoint in the constructor, where self and self.__x ARE in scope.
An alternative, if you want to access it from main, is you just access with the instance instead of with self, like this:
I am not sure what exactly amongst the following worked - but something has
Did an auto code cleanup
Closed down PyCharm and reopened all the files
Methodically went through the entire project and made sure every line of code was very tight without any form of errors.
Now when I set a watch against self.__ and related variables I do not see the error. I think part of the problem was that I wrote the code originally in IDLE and then copied the code across to a PyCharm project. Thus I did not have the PyCharm error checking etc. That meant I had a lot of unnecessary errors etc.

reload the currently running python script

In python ,There is a reload method to reload an imported module , but is there a method to reload the currently running script without restarting it, this would be very helpful in debugging a script and changing the code live while the script is running. In visual basic I remember a similar functionality was called "apply code changes", but I need a similar functionality as a function call like "refresh()" which will apply the code changes instantly.
This would work smoothly when an independent function in the script is modified and we need to immediately apply the code change without restarting the script.
Inshort will:
reload(self)
work?
reload(self) will not work, because reload() works on modules, not live instances of classes. What you want is some logic external to your main application, which checks whether it has to be reloaded. You have to think about what is needed to re-create your application state upon reload.
Some hints in this direction:
Guido van Rossum wrote once this: xreload.py; it does a bit more than reload() You would need a loop, which checks for changes every x seconds and applies this.
Also have a look at livecoding which basically does this. EDIT: I mistook this project for something else (which I didn't find now), sorry.
perhaps this SO question will help you
Perhaps you mean something like this:
import pdb
import importlib
from os.path import basename
def function():
print("hello world")
if __name__ == "__main__":
# import this module, but not as __main__ so everything other than this
# if statement is executed
mainmodname = basename(__file__)[:-3]
module = importlib.import_module(mainmodname)
while True:
# reload the module to check for changes
importlib.reload(module)
# update the globals of __main__ with the any new or changed
# functions or classes in the reloaded module
globals().update(vars(module))
function()
pdb.set_trace()
Run the code, then change the contents of function and enter c at the prompt to run the next iteration of the loop.
test.py
class Test(object):
def getTest(self):
return 'test1'
testReload.py
from test import Test
t = Test()
print t.getTest()
# change return value (test.py)
import importlib
module = importlib.import_module(Test.__module__)
reload(module)
from test import Test
t = Test()
print t.getTest()
Intro
reload is for imported modules. Documentation for reload advises against reloading __main__.
Reloading sys, __main__, builtins and other key modules is not recommended.
To achieve similar behavior on your script you will need to re-execute the script. This will - for normal scripts - also reset the the global state. I propose a solution.
NOTE
The solution I propose is very powerful and should only be used for code you trust. Automatically executing code from unknown sources can lead to a world of pain. Python is not a good environment for soapboxing unsafe code.
Solution
To programmatically execute a python script from another script you only need the built-in functions open, compile and exec.
Here is an example function that will re-execute the script it is in:
def refresh():
with open(__file__) as fo:
source_code = fo.read()
byte_code = compile(source_code, __file__, "exec")
exec(byte_code)
The above will in normal circumstances also re-set any global variables you might have. If you wish to keep these variables you should check weather or not those variables have already been set. This can be done with a try-except block covering NameError exceptions. But that can be tedious so I propose using a flag variable.
Here is an example using the flag variable:
in_main = __name__ == "__main__"
first_run = "flag" not in globals()
if in_main and first_run:
flag = True
None of these answers did the job properly for me, so I put together something very messy and very non-pythonic to do the job myself. Even after running it for several weeks, I am finding small issues and fixing them. One issue will be if your PWD/CWD changes.
Warning this is very ugly code. Perhaps someone will make it pretty, but it does work.
Not only does it create a refresh() function that properly reloads your script in a manner such that any Exceptions will properly display, but it creates refresh_<scriptname> functions for previously loaded scripts just-in-case you need to reload those.
Next I would probably add a require portion, so that scripts can reload other scripts -- but I'm not trying to make node.js here.
First, the "one-liner" that you need to insert in any script you want to refresh.
with open(os.path.dirname(__file__) + os.sep + 'refresh.py', 'r') as f: \
exec(compile(f.read().replace('__BASE__', \
os.path.basename(__file__).replace('.py', '')).replace('__FILE__', \
__file__), __file__, 'exec'))
And second, the actual refresh function which should be saved to refresh.py in the same directory. (See, room for improvement already).
def refresh(filepath = __file__, _globals = None, _locals = None):
print("Reading {}...".format(filepath))
if _globals is None:
_globals = globals()
_globals.update({
"__file__": filepath,
"__name__": "__main__",
})
with open(filepath, 'rb') as file:
exec(compile(file.read(), filepath, 'exec'), _globals, _locals)
def refresh___BASE__():
refresh("__FILE__")
Tested with Python 2.7 and 3.
Take a look at reload. You just need to install the plugin an use reload ./myscript.py, voilà
If you are running in an interactive session you could use ipython autoreload
autoreload reloads modules automatically before entering the execution of code typed at the IPython prompt.
Of course this also works on module level, so you would do something like:
>>>import myscript
>>>myscript.main()
*do some changes in myscript.py*
>>>myscript.main() #is now changed

python class not instantiated - ways to catch/debug?

Im having some trouble with a python module (webpy.session) and Ive narrowed the problem down to a class not being instantiated.
Is there a way I can catch this happening and log the reason/error to a log file?
p.s (Ive tried running it in the python console and it works without error there)
I use pdb to debug this kind of thing.
For example, to debug the code you posted, I would add:
db = web.database(dbn='mysql', db='auth', user='root', pw='')
store = web.session.DBStore(db, 'sessions')
import pdb; pdb.set_trace() # BREAK <<<< this line
session = web.session.Session(app, store, initializer={})
Which would let me step into the function (using s), see what's returned, etc.
Bonus tip, if you use vim: map <F8> oimport pdb; pdb.set_trace() # BREAK<esc>

Categories

Resources