Showing posts with label MacPython. Show all posts
Showing posts with label MacPython. Show all posts

3/15/2005

Using Python to find Type/Creator codes

It has been a while since I needed to know about old-style Mac Type/Creator codes, but today I wanted to search my hard drive for files of a specific type. I thought you used to be able to drag a file into the find file Type box and it would automatically assign the Type to the input box, but this no longer seems to be the case on OS X.



I thought about downloading some utility which would allow me to see the Type code of a file of the same Type as the one I was trying to find, but then I realized I could probably do it with Python, and I was right.




>>> MacOS.GetCreatorAndType('/Volumes/Stormbringer/Audio/New Sessions/Guitar Project/Guitar')
('MOUP', 'PERF')


I also find myself occasionally using the Python REPL to do things like perform some quick math, convert between a char and the ordinal of that char, and look up unicode glyph names and resolve them. Instead of downloading some specific program to do some task, I have access to this vast functionality space which I can use to create my own utilities simply by remembering the steps to perform.



2/21/2004

Running scripts in pythonw from Xcode

The previous tip works fine if your Python script is just a command-line script that doesn't require any interaction with the WindowServer. However, if your script needs to be run with pythonw normally in order to interact with the user in a GUI fashion, it won't work. Xcode won't let you select /usr/bin/pythonw as the executable because it is just a shell script, not a binary executable. To work around this, use /bin/sh as the executable and pass pythonw and your python file as arguments to sh:

Choose Project->New Custom Executable
Type /bin/sh as the Executable Path
Double-click on the new executable
Click the plus button under Arguments and type:
/usr/bin/pythonw /path/to/your/script/here.py

Update: Bob has pointed out in a comment that you can use the executable that the pythonw script runs directly. I have tested it and it seems to work for me. Set the executable path to:

/System/Library/Frameworks/Python.framework/Versions/2.3/Resources/Python.app/Contents/MacOS/Python

And the arguments to the path of your script. Thanks Bob!

2/19/2004

Running Python scripts inside Xcode

It's not terribly difficult to tell Xcode to launch a Python process and start your script, but it comes up now and again, so I thought I would spell out the steps required.

Choose File->New Project.
Choose Empty project.
Choose where to save it and what to name it, and click Finish.

Choose Project->New custom executable
Give the executable any name you want (I usually call it 'python') and *type in* the executable path to the python you want to run (/usr/bin/python or /usr/local/bin/python) and click Finish.
You can now use Debug->Run executable (Command-R) to get a Python prompt. Be warned that you can't send Control-D to this process, and clicking the stop task button rather harshly kills the process. This is the one drawback I have found to using this method.

Now, double-click on the 'python' executable you just created in the Executables list. You will be able to set the launch arguments, environment variables, working directory and more.

Press the plus button under Arguments, and type in the fully-qualified path of your main python script.

It is good if your script can run to completion, so hopefully it is just a script that does something and exits, or if it is an application which enters a mainloop and runs forever, it has some way of externally shutting it down. You can kill it with the stop button, but it's not a clean kill at all.

2/11/2004

CoreAudio from Python

Well, I've only been talking about doing it for 4 years now, but I finally got Python playing some buffers of audio using CoreAudio. It was about a day's worth of hacking, with a few hours on the side nailing down threading issues.

I put the code up here:

http://soundfarmer.com/content/code/coreaudio/

I also put a short description of what it is on the pythonmac wiki:

http://pythonmac.org/wiki/CoreAudio

CoreAudio calls you back in a thread, you see. A thread Python hasn't seen before. Python doesn't like that very much. This isn't the first time I have tackled this issue. CarbonEvents also call you back in a new thread you haven't seen yet. Two years ago when I wrote the CarbonEvent wrappers for Python, there were no convenient ways to deal with this situation. Before you are allowed to request the global interpreter lock, you must have a PyThreadState. You can create a new PyThreadState, but only if you have a PyInterpreterState. And if you are getting called back from a new thread that has never seen Python before, you are pretty much out of luck.
The solution I came up with for CarbonEvents, later on Windows talking to a stupid Asset Management system, and finally for CoreAudio, is to make an initialization call into my module which will eventually be generating callbacks into Python. In this call, I stash the current PyInterpreterState away in a C global. Then, when the new thread comes in and needs to make a PyThreadState you can use the stashed PyInterpreterState.
This time I was trying to use Pyrex to wrap the C calls I needed, partially because I thought it would be fast and easy and partially because I wanted to learn Pyrex. During the build-crash-debug cycle I kept thinking to myself there was an easier way that I had read about a while ago, and I was right: http://python.org/peps/pep-0311.html describes an implementation of an API specifically designed for this situation which is included in Python 2.3.
I'm happy to say it works quite well, and I was able to generate my sine wave in python code. I even went on later and used numarray to wrap the incoming and outgoing buffer for a speed boost.
My favorite thing about Python is that it is trivial for those who aren't afraid of C to get access to literally everything they need, if it's not possible already.