Passing Applescript list to Python function via Do Shell Script

Hi

To speed up list processing in Applescript, I want to make use of some Python built-in functions, such as max(). Can anyone help, me, please, with passing the AppleScript list to the Python function? I can pass a string, but in the following code, the list {1, 2, 3, 10, 1} gets converted into 123101, and Max() thus returns 3 rather than 10.

set inputList to {1, 2, 3, 10, 1}
my maxListPy(inputList)
-----
on maxListPy(inputList)
	
	set theCommand to quoted form of "import sys; print max(sys.argv[1])" & " " & inputList
	return do shell script "python -c " & theCommand
	
end maxListPy

Any help would be appreciated.

Michael

You could loop through the list and put each item into a string, and then pass that string to python. However this wouldn’t give you any speed gain because the python code would be unnecessary because you could just get the max value while you’re looping through the list. So this first script probably isn’t what you want. Notice I fixed your python code too…

set inputList to {1, 2, 3, 10, 1}

set listString to ""
repeat with i from 1 to count of inputList
	set listString to listString & ((item i of inputList) as text) & ", "
end repeat
set listString to text 1 through -3 of listString

my maxListPy(listString)
-----
on maxListPy(inputList)
	set theCommand to "import sys; print max(" & inputList & ")"
	return do shell script "python -c " & quoted form of theCommand
end maxListPy

Another better approach would be to take advantage of a cocoa method. In applescript we can access cocoa methods through automator runner. In your case you can use that to create your string…

set inputList to {1, 2, 3, 10, 1}

tell application "Automator Runner" to set listString to call method "description" of inputList

maxListPy(listString)
-----
on maxListPy(inputList)
	set theCommand to "import sys; print max(" & inputList & ")"
	return do shell script "python -c " & quoted form of theCommand
end maxListPy

In the end though I doubt that python would be faster than applescript. For really large lists where python might be better, remember that you have limits when passing stuff to the shell… so I think that limit would prevent a list large enough to take advantage of python. In the end I’d just use a “reference” to the list to speed it up which is an applescript technique…

set inputList to {1, 2, 3, 10, 1}
maxList(inputList)

on maxList(inputList)
	set theList to a reference to inputList
	set maxValue to item 1 of theList
	repeat with i from 2 to count of theList
		if item i of theList is greater than maxValue then set maxValue to item i of theList
	end repeat
	return maxValue
end maxList

Thank you very much. There are some really interesting ideas there to experiment with. Some of the things I want to do use quite long lists (20,000 or so items from a large iTunes library) and from what you say that will probably rule out ‘do shell script’. Is it possible to put the list-handling code into a separate Python script and to call that in some way from AppleScript? If so, could the list be passed without having to write to and read from disk?

I think your best bet would be to keep everything in python. Then you don’t have to pass things back-and-forth. I’m not a python expert so I’ll show you something that can be done from a shell script.

There is a command line tool called osascript. osascript allows you to run applescript code from the shell. If you can access command line tools from python then this might be the best approach for you. My idea would be to use osascript (eg. applescript) from your python script to bring the list from iTunes into your code.

Here’s an example osascript command.
First way: if you have a compiled applescript file you can run it from the shell using…

osascript path/to/applescript

So that applescript could be a script that queries itunes and gets your list. osascript would run the applescript and pass the results back to the shell.

Second way: if your applescript code is short you don’t need a separate applescript file. You can run lines of applescript code using the -e option of osascript. For example, if you wanted the name of the currently playing track in iTunes you could run it like this from the shell…

osascript -e "tell application \"iTunes\"" -e "set currentTrack to current track" -e "set trackName to name of currentTrack" -e "end tell" -e "return trackName"

Notice each line of applescript code is in quotes and is preceeded by the -e option of osascript. So if python can access command line tools (and I’m sure it can) then you can use osascript to get the list from iTunes right into your python code using osascript.

Thanks. I appreciate the time you have spent helping. Doing the entire thing in Python, and calling AppleScript, may be the best way to go. All I have to do now is to learn enough Python to write that script…