Re: [Pyobjc-dev] execing /usr/bin/python
Brought to you by:
ronaldoussoren
From: <bb...@ma...> - 2002-11-01 21:05:16
|
On Friday, November 1, 2002, at 03:06 PM, Ronald Oussoren wrote: > On Friday, Nov 1, 2002, at 15:55 Europe/Amsterdam, bb...@ma... wrote: >> On Friday, November 1, 2002, at 07:05 AM, Jack Jansen wrote: >> I think we are talking about two different ways of building >> applications. > > ... and I'd like to suppport either way of building applications, if > only because I've vi keyboard commands hardwired into my hands (I tend > to insert sequences of j/k/l/h into when I'm really concentrated while > typing in a GUI editor :-) Thank goodness the AppKit folks were emacs-heads... I have emacs wired in my head and still save documents in Project Builder via C-xC-s half the time. In any case, I totally agree that supporting both ways of building apps should be a priority. >>> On vrijdag, nov 1, 2002, at 03:53 Europe/Amsterdam, bb...@ma... >>> wrote: >>>> On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: >>>>> On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... >>>>> wrote: >>>>>> .... >>>>>> Note that there is no python binary in the app wrapper, only a >>>>>> symlink to one. The *only* substantial difference between the two >>>>>> scheme's is that in Jack's version argv[0] is (a) not the >>>>>> CFBundleExecutable (but still a file located in Contents/MacOS in >>>>>> the application bundle) and (b) sys.executable is automaticly a >>>>>> python interpreter. > > Another minor difference is that is harder to switch interpreters, but > I'd tend to find this an advantage (but hey, I can change the > main-bin-python.m file to not support NSUserDefaults making this a > very minor difference). Switching interpreters should really only be an issue in the developer environment. Once an app is switched, it'll either be hardwired to Apple's interpreter or will have to ship with an alternative interpreter (or require the user to install one). >> The key difference is in the information contained within the >> executable found within the app wrapper. In my solution, the >> executable automatically carries the information about what >> frameworks are used into the python interpreter by simply linking the >> custom executable against the appropriate frameworks. This also >> allows the developer to work directly with the Project Builder >> indices -- for example, If I write "bundle = >> NSBundle.bundleWithPath_(path)", I can command-double-click on the >> word NSBundle and Project Builder takes me straight to the >> declaration for NSBundle (option-double-click displays the >> documentation). > I see the usefulness of using documentation from PB, but the week was > probably slightly too long for me because I fail to see the > usefullness of actually passing information about linked frameworks to > the Python script: You still have to write a wrapper module for the > frameworks, unless you intend to locate all classes by using > objc.lookup_class. Typically, I haven't had to write a wrapper module for the frameworks in those projects where I have custom frameworks built into the application wrapper. The frameworks may be composed of Obj-C code that the python code never directly refers to (in my case, a couple of window controllers that set up some table views with some custom NSCell subclasses). Another advantage to linking the frameworks into the custom executable in the app wrapper [with the autoloading mechanism] is that it enables automatic prebinding. The frameworks are built with an install_name of @executable_path/../Frameworks/* (as required by frameworks encapsulated in an app wrapper). The automatic prebinding on 10.2 picks this up and re-prebinds the frameworks, as needed. The unfortunate side effect is that a couple of environment variables must be propagated prior to loading the frameworks, but that will always be the case if (a) the frameworks are to be dynamically loaded by the interpreter and (b) one framework links against the other. Actually, come to think of it, the only way to use frameworks with the python command line interpreter where one framework links against another and the two frameworks are included in the app wrapper is to use execve() to pass control to the interpreter as the DYLIB environment variables must be set before the executable is launched! (This'll all probably make very little sense to anyone but the folks that have been down that particularly painful path.) >>> I would think this works the same as Bills scheme, with the only >>> exception that sys.executable points to a python interpreter, so >>> something like system(sys.executable + " myscript.py") will work. >> >> Two solutions: >> >> (1) In Main.py (or __main__.py -- is that "more standard"?), set >> sys.executable to whatever python interpreter the user has selected >> (in my solution, that would mean reading the 'PythonBinPath' user >> default in a similar fashion as the bootstrap executable). > BuildApplication/BuildApplet in MacPython name the principle python > file in the created application __main__.py, I suppose because the > __main__ is the name of the 'toplevel' module and can therefore not be > used for normal code (e.g. you cannot accidently overwrite a module > when renaming the principle python file to __main__.py). Works for me. I'll change it as I have a chance. >> (2) Make it such that the second invocation of sys.executable >> [which points to the bootstrap binary in my app wrapper] simply calls >> execve() with a command line that passes control to python along with >> the arguments. I.e. put recursion protection on that executable. >> The overhead of an extra execve() is trivial in comparison to the >> overhead of a full blown GUI. > This sounds pretty ugly. Actually implementing this correctly is hard, > unless you implement the wrappper in python. Wwwweeeeelllll.... it could be done by setting an environment variable before the call to execve(). If that environment variable is set, it would do the pass-straight-to-python-interpreter style execve(). Of course, if someone were to fork out and subshell to another GUI app directly, it'd break -- but, then again, you aren't supposed to invoke GUI apps in this fashion anyway. Yes, ugly. Hard. Yuck. b.bum |