Kodi Community Forum

Full Version: Python: save reference to a thread
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi guys, some python-hackers out there? Big Grin

I'm trying to run some persistent code:

A plugin starts a thread, the plugin exits but the thread keeps running.
The next time the plugin is started i need to interact with the already running thread.

How can I store a reference of that thread?

I managed to get a function address but python doesn't allow calling by address.
Whats the use case? Wouldnt a service be a better structure than a plugin?
I intentionally didn't explain what/why I want to do this because it distracts from the question Wink
I'm new to python and this problem (the solution) would help me understand the inner workings.

But here you go:
I'm trying to speed up a rather large video plugin on the RaspberryPi.
It takes 2.5s just to load the plugin and all the imports before the first function is executed.

By running the plugin as a thread and communicating with it this delay is gone.
I already got it working by passing the arguments via xbmcaddon.Addon().setSetting()
But the thread is in an infinite loop, constantly checking if the setting has changed and that uses quite a lot of cpu.

Maybe there is a better way for passing the arguments?

But like i said:
I'm interested in saving the reference because that would teach me a lot about python.
If i can understand the solution Rofl
I am doing that same sort of thing for LazyTV. There is a service that takes care of maintaining a list of TV episodes, and the script calls the data from there.

The "while not abort requested" loop is fairly commonly used in addons that are kept alive. The benefit is that when XBMC exits you can exit the script in an orderly way. And I dont think it costs much in CPU is you have it sleep for a short amount of time.

Code:
while not xbmc.abortRequested:
    xbmc.sleep(100)
    your code

If you dont care about that then, you could have your script communicate with your service via a socket. This will allow your service to wait for a connection (though I dont know how much difference there is between that and just the while loop.)
(2014-10-19, 10:47)Karnagious Wrote: [ -> ]... and the script calls the data from there.

How does it get the data?

(2014-10-19, 10:47)Karnagious Wrote: [ -> ]The "while not abort requested" loop is fairly commonly used in addons that are kept alive. The benefit is that when XBMC exits you can exit the script in an orderly way. And I dont think it costs much in CPU is you have it sleep for a short amount of time.

That's how I'm doing it, I think the cpu is used by xbmcaddon.Addon().getSetting().
My idea is directly setting variables of the thread object, polling that should be much faster.

Maybe I should look into sockets some more, I already thought about it but decided against it:
1. I want to keep the script as small as possible, if I import lots of stuff it's not going to be any faster than it was before
2. As I understand it the socket server has to poll for incoming connections, no difference to polling in the thread directly
Did your code have the xbmc.sleep line? Thats fairly important in preventing excessive cpu use.

The benefit of the socket is that you will always know the required reference. You are also able to pickle and send python objects (like dictionaries) without having to worry about converting them to strings and then evaluating them back to the object. I wanted to be able to send xbmc ListItems, but they dont pickle, unfortunately.

What is the script importing? Maybe there is one particular troublesome module?
yes it is sleeping, I'll try replacing xbmcaddon.Addon().getSetting() to see if this indeed is using up the CPU.

pickle is of no use since it creates a new instance of the object but I need the already running one.

The two biggest modules are CommonFunctions and metahandler, each takes almost 1s to import.

How do you exchange data between the service and the script?
Are you using file or is there a direct way?

I read somewhere that it should be possible with a jsonrpc announce but I haven't found out how to receive the message in a script
If importing is slow then try making your plugin simpler and remove things you don't need like importing huge modules. Communicating over a socket and pickling is not going to make that any faster, probably the opposite!

GreenAir Wrote:By running the plugin as a thread and communicating with it this delay is gone.
It's how plugins in xbmc works: every time you enter/change a directory in a plugin, it runs the python script from scratch and wait for it to finish. I understand what you are trying to do, but this is not something you can fix in python. PS: make sure you run the plugin more than once when measuring performance, because the first time after you change something will always be slower than the rest.
ok, now we definitely lost sight of my original question Wink

It's not my plugin and it is really fast on my PC-system but on the slow RaspberryPi it takes some time to load.

By keep it running in a thread i only have to make minimal changes to the plugin and just add my wrapper so it's easy to update.

The alternative would be restructuring the whole plugin to only import the needed modules for each action but that's not really feasible.

I already have it running a lot faster: 1.5s against 2.7s for a whole execution, the one thing that is still holding it back is the awkward parameter passing by polling xbmcaddon.Addon().getSetting()

I'm searching for a way to interact with the running thread or another way of passing values between scripts.
I've done it!

An action that took around 2.5s is now done in 0.1s!!!!! Cool
yessssssssss!!!! Laugh

I'm using xbmcgui.Window().setProperty() to pass the values, i'm not happy how i've done it but i'm thrilled by the result
Which plugin was it?

If it works better for the Pi, then maybe consider making it an official fork and allow others to use it.
I don't know if i'm allowed to talk about it because it is for streaming movies and TV-shows.
It is legal here in Switzerland but I'm not familiar with the guidelines here in the forum.

I'm definitely posting it as a 'special' version and contact the author of the original plugin if he wants to include it in his repository.
(2014-10-19, 15:24)GreenAir Wrote: [ -> ]I don't know if i'm allowed to talk about it because it is for streaming movies and TV-shows.
It is legal here in Switzerland but I'm not familiar with the guidelines here in the forum.

I'm definitely posting it as a 'special' version and contact the author of the original plugin if he wants to include it in his repository.

Ah. Quite so.

That is definitely the way to go Smile
Trying to revive this thread....

I found a ugly workaround for my specific problem but haven't found a solution to the question:

Is there a way to save a reference to a thread?
You should try to explain the problem you are trying to solve in a more general way, or reconsider showing that code, because the question of how "to save a reference to a thread" doesn't make much sense. I don't think reference and thread means what you think it means.
Pages: 1 2