Python Forum
Returning data from a pyobjc object to python environment
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Returning data from a pyobjc object to python environment
#1
Hi all

Sorry in advance if this is a basic question - new to python over the recent lockdown and have never ever used objective C...

To start with - this is not homework but a personal project i am trying to do to develop an understanding of python and the bridge to running things on a Mac

I am looking to return a list of data from an objective-C object generated in python:
Briefly the aim of the project is to listen for a track change and then do some processing with the data depending on the track genre etc.

I have managed to get code to:
run an applescript whilst listening for track changes form the music app
print the information to the console - thanks to this link: https://gist.github.com/codiez/260617

However when I have tried to access the information outside the class it says it is not defined:
Error:
AttributeError: 'getSongInfo' object has no attribute 'this_song_info'
Below are the methods I have tried to use to define the information as a class attribute and return it every time the notification observer reacts:

class getSongInfo(NSObject):
	#attempt 3 - make it a global variable so it is returned whenever 
    global this_song_info
    this_song_info = [None]*5

    def init(self):
        self = super ( getSongInfo, self ).init()
        nc = Foundation.NSDistributedNotificationCenter.defaultCenter ()
        nc.addObserver_selector_name_object_ ( self, 'getMyData:', 'com.apple.Music.playerInfo', None )
        return self

	# attempt 1 - run a method after calling the observer - fails
    # def run_script(self):
        # my_script = applescript.AppleScript (path_to_script)
        # self.this_song_info = my_script.run()
        # return self

	# attempt 2 - make it a property by running the above code
    this_song_info=property(run_script)

    def getMyData_(self, data):
        my_script = applescript.AppleScript ( path_to_script )
		#attempt 4 - assign to self and return every time this pyobjc method is called
        self.this_song_info = my_script.run()
        return self
		 return this_song_info

GetData = getSongInfo.new ()
print(GetData.this_song_info)

AppHelper.runConsoleEventLoop()
I also use the following imports:

from PyObjCTools import AppHelper
import objc
from Foundation import *
import applescript
Reply
#2
I haven't worked with this interface before, but just from looking at this bit here, I have some suggestions for you to try:
GetData = getSongInfo.new ()
print(GetData.this_song_info)
 
AppHelper.runConsoleEventLoop()
runConsoleEventLoop() sounds like this is the point where your code would start looking for data. Even if there wasn't an error in your code, GetData.this_song_info would probably be just empty, as it hasn't yet had a chance to be filled with data.

I would recommend you try adding your processing in the event handler (getMyData_(), in this case).
Reply
#3
You should not use the "global this_song_info". This tells Python that "this_song_info" is defined in the global (module) scope, so when you call "this_song_info = [None]*5" it sets the global module variable instead of making a class variable.

This code does not throw an error. Even though the assignment to "thing" appears inside the class definition, the "global thing" sets the scope for "thing" to global (module)
class MyClass:
    global thing  # Because of global declaration
    thing = 'Hi'  # this does not create a class variable

a = MyClass
print(thing)   # thing is global.  MyClass.thing does not exist
To make this_song_info a class variable the change you need to make is simple. Just remove the global declaration.
class getSongInfo(NSObject):
    this_song_info = [None]*5  # Now this is a class variable
Reply
#4
(Jul-25-2020, 11:23 PM)nilamo Wrote: I haven't worked with this interface before, but just from looking at this bit here, I have some suggestions for you to try:
GetData = getSongInfo.new ()
print(GetData.this_song_info)
 
AppHelper.runConsoleEventLoop()
runConsoleEventLoop() sounds like this is the point where your code would start looking for data. Even if there wasn't an error in your code, GetData.this_song_info would probably be just empty, as it hasn't yet had a chance to be filled with data.

I would recommend you try adding your processing in the event handler (getMyData_(), in this case).

Thank you very much for the reply

The further processing includes opening a tkinter window and i did try and add it into the getMyData_ call but the window never appeared - hence the need for passing the data back "outside" of the pyobjc call
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python: Returning the most frequently occurring substring in a larger string sskkddrit 2 4,008 Feb-09-2018, 06:41 AM
Last Post: sskkddrit

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020