On May 16, 2005, at 2:53 PM, [EMAIL PROTECTED] wrote: > > On May 16, 2005, at 1:22 PM, Bob Ippolito wrote: > > >> >> On May 16, 2005, at 2:01 PM, [EMAIL PROTECTED] wrote: >> >>> The debugged app works like that, but the way that the "remote >>> object" interface works is also designed to use sync TCP on the host >>> side. Since it's pure python, I didn't want to start adding in >>> NSFileHandles, and the obvious solution was "just use threads", and >>> the whole "block on reads" model was much cleaner than any sort of >>> polling. >> >> This isn't a very good argument since you're already using plenty >> of Objective-C code in there. > > My goal was to try to not make it worse... (since part of the goal > was to be able to provide a debugging stub that could be included > in anything that embedded python, regardless if it was PyObjC based > or not - or even Mac OS X based).
The important part is to make what sits inside the running program pure python with no non-stdlib dependencies. The part that lives in the IDE is going to have so much IDE specific code in it that it doesn't really matter whether you're using pure python or not. >>>> If you need a way to interrupt the debugged app asynchronously >>>> (i.e. ctrl-C in gdb), then set up a signal handler in the debugged >>>> app that installs a trace hook from the debugging bootstrap code >>>> that makes it go into debugging mode and send it a signal from the >>>> host app... but that's not something that's ever very clean in >>>> Python. >>>> >>>> >>> >>> I haven't quite figured out a good way to handle that one either, >>> but >>> since the other app is a child, sending a signal should work as good >>> as anything. >>> >>> >> >> There's a "you probably shouldn't use this" function in the C API >> that lets you write an extension module that sends an exception to >> another thread, so in theory you could start a background thread >> that sits on this and waits for a "signal" over TCP or the like >> from the parent and then uses that to break into the main thread. >> Don't do this though, there's a lot of reasons not to. >> >> Alternatively, you could start up a second socket on another >> thread and use it to send a signal to its own pid if it hears from >> the host. This would facilitate true remote debugging. >> >> > > I should be able to directly send the signal from the IDE to the > targeted app (since it's a child of the IDE), and the standard > "catch a unix signal invokes the debugger" action should work > (since the debugger interface on the client talks back to the IDE). Yeah, this will work fine. I'm just saying, that if you wanted something even more decoupled (to implement remote debugging, plugin debugging, objc.inject debugging, etc.), then that's how you could do it. >>>> Update to PyObjC from svn and see if that makes a difference. >>>> >>>> >>> >>> Can't do that - the goal is to provide something that, at worse, >>> requires the user to install a given binary package (PyOXIDE is >>> designed to directly call packman if it detects PyObjC not being >>> installed, to make things as transparent as possible). If I require >>> the user to download the latest sources and compile it, that becomes >>> a nightmare. If I compile it myself from "latest beta" and >>> included >>> it with PyOXIDE, that prevents bug fixed releases (since PyOXIDE >>> would be hardcoded to run on the older, buggier, pre-release >>> version). >>> >>> There's already far too much "well, it will all work great, but >>> first >>> you need to download this (and then compile that, and install this >>> third thing)..." in the MacPython world that it makes me cringe (and >>> certainly the choice of versions of Python included with the OS >>> don't >>> make the problem less either). Unfortunately, I can't think up a >>> good way to solve that problem so I just cringe a lot and try to not >>> make anything worse... >> >> Well that's too bad. What you're suggesting will make things much >> worse. >> >> The Python interpreter used by your application should be private >> anyway, so you can and should include PyObjC (probably even Python >> itself) inside your application. >> > > Including an entire "custom" version of Python just seems like a > bad solution to me. It may be the only solution, depending on > various other circumstances, but it seems kind of sad to say "well, > OS X ships with Python.framework, but it can't be used to write a > Python IDE". Mac OS X 10.3 and 10.4 ship with a Python 2.3 framework. Mac OS X 10.5 (hopefully) will not. Do you want to have to maintain separate versions of your app for 10.3-10.4 and 10.5, so as to use the standard Python? Additionally, do you want to test everything on Python 2.3.0 and Python 2.3.5? What if you run into a bug that can't be monkeypatched for Python 2.3.0? There's so many reasons NOT to use the framework that Apple provides, because they do a really poor job maintaining it, and provide no guarantee of backwards or forward compatibility of any sort... unlike their own frameworks. >> I've said this a ton of times, but the ONLY time you should EVER >> run user Python code from an IDE is from separate processes, >> unless it's simply a plugin for the IDE. > > I personally don't agree with this. There are plenty of times when > I just need something to "tinker" with, and the separate process > model doesn't work well because I find the ability to have a semi- > persistent state extremely useful (run the script, examine the > results using an interactive window, manually call some of the > routines, fix a routine and run that source file again, etc... - > not to mention that examining the state of objects within the > application is _much_ faster than having to proxy everything > through a socket). Now if there were a "persistent external" mode, > that would be another story (but that's more a "future feature"). Semi-persistent state can be had just as easily with an external interpreter using the same methodology you're using for a debugging stub. If the interpreter is already open, then just call execfile in it instead of tearing it down and starting another one. No problem there, and you don't have to worry about forcing the user to use the IDE's version of Python nor do you have to worry about the IDE crashing, hanging, becoming unstable, blowing up, etc. because the user decided to call NSApp().terminate_(None) or something. As far as speed goes. If it's noticeably slower than you're doing something wrong. Safe and correct is better than fast, anyway, ESPECIALLY for an IDE. The last thing you want is the IDE to crash in the middle of doing something. As far as I've seen here, the major complaint with your PyOXIDE is that it is not stable, so perhaps you should change your viewpoint on issues like this. Speed is easy enough to fix anyway, there are plenty of ways you could put more code in the stub or use mmap to transfer memory or whatever else as an *optimization after it already works correctly* without compromising the integrity of the host application. >>> After a good burrito for lunch, I'm thinking that adding an >>> unlockPythonAndPerformSelectorOnMainThread(andRelockAfterwards) >>> method might be the best way to handle this - at least it's >>> something >>> easy that I can add as part of PyOXIDE... >> >> NO! That is really really horribly bad to do. Working around a >> bug in PyObjC by writing code that will break in correct versions >> of PyObjC is absolutely horrible. You should NEVER release the >> lock unless you own it. > > Here, then, is probably the heart of the problem - the interactions > between python threads spawned by threading.Thread and the main > (objc) thread and performSelectorOnMainThread are "undefined", and > the more I look at it, the more it appears that using > threading.Thread in a PyObjC app is a bad idea and should probably > just be chalked up as "unsupported and probably won't work". It > appears that I'd need to build something on top of NSThread (in > Objective-C) with explicit thread state handling to get this to > work consistently and correctly. Well, that's simply not true. PyObjC svn + Python 2.4.1 definitely does not have this problem. There was a thread about this (aptly named "Threading") on pyobjc-dev in March/April. I suggest you subscribe there if you haven't already. The issue you're experiencing is a bug in Python 2.3.0 (another reason not to use Apple's Python framework on Panther). This is in the interpreter of course, so it can't be fixed in-place and Apple sure isn't going to update it. Python 2.4.1 and reportedly Python 2.3.5 do not have this bug. Yet another /really/ good reason not to use the Python framework that ships with Mac OS X 10.3! The only edge case, of course, is that Foundation must be in "threaded" mode before you start calling into objc from the second thread, which generally happens behind the scenes anyway because you're using AppKit which will start a thread or two off the bat. This is a general restriction of using "raw" pthreads from any Foundation app. PyObjC should probably spawn a NSThread during initialization, I'll go ahead and do that before the 1.3.5 release. -bob _______________________________________________ Pythonmac-SIG maillist - Pythonmac-SIG@python.org http://mail.python.org/mailman/listinfo/pythonmac-sig