Global functions?

Do you have questions about writing plugins or scripts in Python? Meet the coders here.
User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Global functions?

Post by Luca Brasi » Sat Sep 16, 2017 8:53 am

Hey guys,
I guess this must have been discussed before but I couldn't find anything about it:
Sometimes I'd like to access some functions from different scripts. Like accessing eg.globals.[variables]
This would come in handy for osd loops, find window stuff or checking if processes are running and alike.
As far as I can see I will have to define each function in each script.
I tried to define functions like

Code: Select all

def eg.globals.check_mp():
    eg.globals.mp_running = len( WMI.ExecQuery('select * from Win32_Process where Name="MediaPortal.exe"') ) > 0
The main reason for having it in a function in that case is that I can have it run in another thread. But this is just a short example.
Is there any way to do this?
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Global functions?

Post by yokel22 » Sat Sep 16, 2017 9:34 am

Yes, you can assign functions as eg.global variables like this.

Code: Select all

def myFunction():
    'do stuff' 

eg.globals.newFunction = myFunction
Or

Code: Select all

 def check_mp():
    eg.globals.mp_running = len( WMI.ExecQuery('select * from Win32_Process where Name="MediaPortal.exe"') ) > 0

eg.globals.check_mp = check_mp

You'll need to initialize the variable functions each time eg starts. I usually use the Main. OnInit event that's generated on eg load.

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Global functions?

Post by Luca Brasi » Sat Sep 16, 2017 10:19 am

Great man, thanks!
One simple line eg.globals.newFunction = myFunction :-)
Before when I tried to assign the function directly to the global I got a syntax error.
This will help me a lot!
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
kgschlosser
Site Admin
Posts: 5146
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Global functions?

Post by kgschlosser » Sat Sep 16, 2017 12:40 pm

there is one hiccup when using the Main.OnInit gets triggered after all of the plugins load. there is the possibility that a plugin can trigger an event before the Main.OnInit anf if that event that gets triggered is in a macro that makes use of a global that has not been set up yet you will get the ugly red.

So if you add the TiggerEvent Action and have it trigger an event that you can assign to setting up all of your global functions and attributes and place that Action at the very top of the Autostart then this problem cannot occur
If you like the work I have been doing then feel free to Image

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Global functions?

Post by Luca Brasi » Sat Sep 16, 2017 2:46 pm

Thanks for the heads up. I had seen this before with global variables and set it up as you recommended
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
yokel22
Experienced User
Posts: 265
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Global functions?

Post by yokel22 » Sat Sep 16, 2017 4:18 pm

Yep, it's pretty handy sometimes. Something I didn't even realize you could do for way too long.

User avatar
kgschlosser
Site Admin
Posts: 5146
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Global functions?

Post by kgschlosser » Sat Sep 16, 2017 9:36 pm

this is how you can do proper socket and file closing if you are running a thread from a python script. You would build a class inside of the script and construct the class and set the instance of that class into a global. this class would house the running thread and you can set an event listener so when Main.OnClose gets triggered it will close down the thread properly if the thread is running.


example code

Code: Select all


import threading

class ThreadClass(threading.Thread):

    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2
        self._event = threading.Event()
        threading.Thread.__init__(self, name='SomeThreadName')

    def start(self):
        eg.Bind('Main.OnClose', self.stop)
        threading.Thread.start(self)

    def run(self):
        # startup code
        print 'Thread started'

        # looping code
        while not self._event.isSet():
            # do your looping code here and access the params if needed

            # non blocking sleep
            eg.TriggerEvent(prefix=self.param1, suffix=self.param2, payload='EventPayload')
            self._event.wait(1.0)

        # closing code
        print 'Thread closed'

    def stop(self, dummyEvent=None):
        if self.IsAlive():
            eg.Unbind('Main.OnClose', self.stop)
            self._event.set()
            self.join(1.0)
        return False

# you could set this instance at startup of EG and then 
# make the calls to start and stop it whenever.
# it will always close properly if you close EventGhost

eg.globals.some_thread = ThreadClass('EventPrefix', 'EventSuffix')

eg.globals.some_thread.start()

# use this to close the event.
# eg.globals.some_thread.stop()

If you like the work I have been doing then feel free to Image

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Global functions?

Post by Luca Brasi » Sun Sep 17, 2017 8:05 am

Dude. You need to stop throwing stuff like that at me on a Sunday morning. My girlfriend is gonna kill me pretty soon :D
No honestly thank you very much. I love to learn how to do it in coding.
Until now I have been using the AddTask action for calling the functions. Can you tell me what's the difference in doing it with the code compared to AddTask?

And maybe I didn't understand entirely yet but if I try your code like this I will get an error about IsAlive

Code: Select all

import threading
class ThreadClass(threading.Thread):

    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2
        self._event = threading.Event()
        threading.Thread.__init__(self, name='MyTestLoop_1')

    def start(self):
        eg.Bind('Main.OnClose', self.stop)
        threading.Thread.start(self)

    def run(self):
        # startup code
        print 'Thread started'

        # looping code
        while not self._event.isSet():
            # do your looping code here and access the params if needed
            import time
            for x in range(0,10):
                print x
                time.sleep(1)
            else:
                break
            # non blocking sleep
            eg.TriggerEvent(prefix=self.param1, suffix=self.param2, payload='EventPayload')
            self._event.wait(1.0)

        # closing code
        print 'Thread closed'

    def stop(self, dummyEvent=None):
        if self.IsAlive():
            eg.Unbind('Main.OnClose', self.stop)
            self._event.set()
            self.join(1.0)
        return False

# you could set this instance at startup of EG and then
# make the calls to start and stop it whenever.
# it will always close properly if you close EventGhost
eg.globals.MyTestLoop_1 = ThreadClass('EventPrefix', 'EventSuffix')
eg.globals.MyTestLoop_1.start()
import time
time.sleep(5)
# use this to close the event.
eg.globals.MyTestLoop_1.stop()

Code: Select all

09:57:42   ---> Welcome to EventGhost <---
09:58:19   thread definiton
09:58:19      Thread started
09:58:19      0
09:58:20      1
09:58:21      2
09:58:22      3
09:58:23      4
09:58:24      Traceback (most recent call last):
09:58:24        Python script "42", line 49, in <module>
09:58:24          eg.globals.MyTestLoop_1.stop()
09:58:24        Python script "42", line 35, in stop
09:58:24          if self.IsAlive():
09:58:24      AttributeError: 'ThreadClass' object has no attribute 'IsAlive'
09:58:24   5
09:58:25   6
09:58:26   7
09:58:27   8
09:58:28   9
09:58:29   Thread closed
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
kgschlosser
Site Admin
Posts: 5146
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Global functions?

Post by kgschlosser » Sun Sep 17, 2017 2:53 pm

I fat fingered the IsAlive() it is supposed to be isAlive() lowercase i
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 5146
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Global functions?

Post by kgschlosser » Sun Sep 17, 2017 3:04 pm

also this is a thread and the loop is already set up for ya with the

Code: Select all

while not self._event.isSet():
this is the loop. the only thing that will break the loop is self._event.set() which you can see gets called when you close the thread. you can also call the self._event.set() from inside of the loop if an error happens and you want to shutdown the thread

the second thing is the use of time.sleep. you do not want to use this. it will block the thread being terminated with self._event.set(). when you call self._event.wait() it is basically the same thing as time.sleep() except that it will stop waiting/sleeping if self._event.set() gets called. time.sleep() does not. it will continue to sleep until the timeout period has expired. the problem with this is if you have a long wait period say 10 seconds the issue with this is that EG will only wait for 5 seconds for a thread to exit properly before throwing an error. and no one really likes to restart eg and have the process get stuck for 5 seconds before it closes.

try this code. this will print 0-9 one number every second and then exit the thread when it is done.

Code: Select all

    def run(self):
        # startup code
        print 'Thread started'
        x = 0

        # looping code
        while not self._event.isSet():
            print x
            x += 1
            if x == 10:
                self._event.set()
            else:
                 # non blocking sleep
                self._event.wait(1.0)
If you like the work I have been doing then feel free to Image

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Global functions?

Post by Luca Brasi » Sun Sep 17, 2017 3:19 pm

Ah yes I understand... I'll check the code later! Thanks man!
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
kgschlosser
Site Admin
Posts: 5146
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Global functions?

Post by kgschlosser » Sun Sep 17, 2017 3:39 pm

make sure you change that IsAlive to isAlive

and no worries m8 that's why I am here
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 5146
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Global functions?

Post by kgschlosser » Sun Sep 17, 2017 3:45 pm

Luca Brasi wrote:Dude. You need to stop throwing stuff like that at me on a Sunday morning. My girlfriend is gonna kill me pretty soon :D
No honestly thank you very much. I love to learn how to do it in coding.

HA! I know right. But you have been around these boards for an extremely long time and You have a working knowledge of the syntax (one of the hardest parts of learning how to program) just got to show you the tools that are available. Good thing to do is to make a new bookmark category and bookmark these pages for reference. what i personally do is i made a folder on my desktop called code snippits and I create a new file and paste the code into it and name the file in a way so that it is something that you will remember so you can bring it back up when you need to use it.

Remember i saw your configuration tree! I am thinking you have been trimming the proverbial fat from it with all of the new information that has been posted.
If you like the work I have been doing then feel free to Image

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Global functions?

Post by Luca Brasi » Mon Sep 18, 2017 5:39 pm

Ok man, thanks again for all the info :D
I'm playing around with the code right now. I am running into problems when I try to call the class with parameters.
As far as I can see you already included that with param1 and param2.
But those two are defined in the startup script which defines the global function. This is done with

Code: Select all

eg.globals.MyTestLoop_1 = ThreadClass('EventPrefix', 'EventSuffix')
So how can I call the function from outside this script and pass some other parameters instead of ('EventPrefix', 'EventSuffix')? I was thinking about using global variables and it works. But this doesn't make any sense to me because the class is defined before when the globals are not set yet.

Code: Select all

eg.globals.MyTestLoop_1.start(param1,param2)
Will not work for obvious reasons:

Code: Select all

19:06:27      Traceback (most recent call last):
19:06:27        Python script "43", line 5, in <module>
19:06:27          eg.globals.MyTestLoop_1.start('Hello1', 'Hello2')
19:06:27      TypeError: start() takes exactly 1 argument (3 given)
I do understand why this is happening. I'm after all calling the function with the start argument and 'Hello1', 'Hello2' should be passed additionally.

And the thread seems not be closed properly because I will get this:

Code: Select all

19:38:12   thread definiton
19:38:16   Python Script
19:38:16      Thread started
19:38:16      Hello1
19:38:16      Hello2
19:38:16      0
19:38:17      1
19:38:18      Closing the thread
19:38:18       2
19:38:18      Thread closed
19:38:26   Python Script
19:38:26      Traceback (most recent call last):
19:38:26        Python script "51", line 4, in <module>
19:38:26          eg.globals.MyTestLoop_2.start()
19:38:26        Python script "50", line 13, in start
19:38:26          threading.Thread.start(self)
19:38:26        File "threading.pyc", line 730, in start
19:38:26      RuntimeError: threads can only be started once
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Global functions?

Post by Luca Brasi » Tue Sep 19, 2017 2:18 pm

Okidoki, I solved the first one:

Code: Select all

import threading
class ThreadClass(threading.Thread):

    def __init__(self):
        self._event = threading.Event()
        threading.Thread.__init__(self, name='SomeThreadName')

    def start(self, param1, param2):
        self.param1 = param1
        self.param2 = param2
        eg.Bind('Main.OnClose', self.stop)
        threading.Thread.start(self)

    def run(self):
        # startup code
        print 'Thread started'
        print str(self.param1)
        print str(self.param2)
        x = 1
        # looping code
        while not self._event.isSet():
            print x
            x += 1
            if x == self.param2:
                self._event.set()
            else:
                 # non blocking sleep
                self._event.wait(self.param1)

        # closing code
        print 'Thread closed'

    def stop(self, dummyEvent=None):
        if self.isAlive():
            eg.Unbind('Main.OnClose', self.stop)
            self._event.set()
            self.join(1.0)
        return False

# you could set this instance at startup of EG and then
# make the calls to start and stop it whenever.
# it will always close properly if you close EventGhost

eg.globals.some_thread = ThreadClass()

#eg.globals.some_thread.start()

# use this to close the event.
# eg.globals.some_thread.stop()
starting it with:

Code: Select all

eg.globals.some_thread.start(1.0, 10)
I still get the error that the thread can not be started again

Code: Select all

   Traceback (most recent call last):
     Python script "7", line 1, in <module>
       eg.globals.some_thread.start(1.0, 10)
     Python script "6", line 12, in start
       threading.Thread.start(self)
     File "threading.pyc", line 730, in start
   RuntimeError: threads can only be started once
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

Post Reply