Python 3.x Progress Update
Python 3.x support has been a topic of discussion here for years, and I finally have some news on that front. :)
As I've teased a bit earlier on Twitter, I'm working on a version of Pythonista that is based on Python 3.5.1 instead of the current 2.7.5. I've made pretty good progress recently, and the app is already in a completely usable state with most custom and third-party modules working. The app's UI is essentially identical to Pythonista 2.0.
Things that are working so far:
- Python 3.5.1 with all new syntax features and most standard library modules (exceptions are basically the same as in 2.x, i.e. mostly Tkinter)
- Numpy, matplotlib, Pillow, PyCrypto, and most other third-party modules that are currently included in Pythonista 2.0 (in some cases more recent versions than in 2.0)
- Most custom modules (
Not working yet:
- A few custom modules (currently only
- The app extension (invoking Pythonista from the share sheet)
- The URL scheme
- The documentation browser
- The example scripts aren't completely ported yet
- A couple of third-party modules that are included in Pythonista 2.0, but aren't (yet?) compatible with Python 3 (screenplain, midiutil, mechanize, xhtml2pdf)
There are probably still a few bugs in the ported versions of my custom modules. Getting the string/unicode handling to work right has been tricky in some cases, and I haven't tested all modules very thoroughly yet.
I expect that I'll have the first beta ready within the next week or so, hopefully without some of the limitations I've listed above. I'll post a new beta signup form here when I'm ready.
Lastly, this will be a separate app, or "paid upgrade" if you will. This is, by the way, one of the reasons I did not charge for the 2.0 update. It'll co-exist with Pythonista 2.x for a while because there are still valid reasons to prefer Python 2.7, and I don't want to force people to upgrade to a version that is not backwards-compatible.
As I've mentioned before, creating an app that supports both Python 2 and 3 would be very difficult, if not impossible. The only way this could theoretically work would require relaunching the app in order to switch versions, and I honestly think that having Python 3 in a separate app will result in a better user experience and less confusion. It will be possible to access files in Pythonista 2.x from 3.x though (and vice-versa).
@dgelessus , ok thanks. My default interpreter is set to 2.7. But it explains what is happening. Guessing it's not the wanted behavior in this case
@JonB It occurred to me I could run it in python2 now that the beta supports both. Then it occurred to me that I could run the old dropbox module using python2 (until dropbox deprecate it at least), so I tried that and got it working. Win. Thanks for your help.
btw, I tried pip install dropbox in stash under 2.7, but it didn't work. It seemed to complete the install, but I still got the same errors from the dropbox sync script (under 3.5), I'm guessing pythonista keeps seperate modules for the two versions or something? I'm not too fussed because I have a working solution now, but I figured it was worth mentioning.
yes.. python3 has a different site-packages. You can copy the folder in stash
I would suggest simply putting #!python2 at the start of launch_stash.py, to force stash to use the python2 interpreter. you can still keep your default interpreter as py3, but run stash using py2.
This is probably a much better solution than porting the whole thing to py3?
A follow-up question is : how can stash run a python script with the other Python interpreter (3.5) while stash itself is running in 2.7? Or vice versa, what if stash is running with Python 3.5 and the script has a python2 shebang?
Currently stash just uses the
execfunction to run a python script which does not seem to honour the shebang. I'd guess this is possible with
objc_util, but I am not sure where to start. Any tips are appreciated.
Maybe @omz can provide a formal API to allow this kind of cross interpreter call?
The editor delegate (_editor_pythonista._get_editor_tab()) has a few new methods
void runScriptAtPath_withInterpreterVersion_arguments_( object, int, object ) void runScriptAtPath_withInterpreterVersion_scriptForShebang_arguments_( object, int, object, object ) void runScriptWithNonDefaultPythonVersion( )
i have used the last, which runs the current editor script in the other interpreter, but not been able to get the first two working. (Though I now think this maybe runs the current script with a different path, as opposed to running a different script)
I suspect exploring the wrench menu might yield some clues, but i have not done that yet.
There is also a PythonInterpreter
ObjCClass('PythonInterpreter').sharedInterpreter()which looks promising, but i have not explored.
oh, i see,there is also a PA3PythonInterpreter which provides access to the p3 interpreter. I have not yet tried any of the runScript commands, I assume they take an NSURL.
>>> print_methods('PA3PythonInterpreter') PA3PythonInterpreter Class Methods______ object sharedInterpreter( ) _______Instance Methods______ object completionsForREPL_( object ) object defaultPythonPath( ) void dispatchBlockOnInterpreterThread_( @? ) void doDispatchBlockOnInterpreterThread_( @? ) void doJediCompletion_( object ) object documentsDirectory( ) void evaluateLineInteractively_( object ) object filteredCompletions_withPrefix_( object, object ) object init( ) char interpreterReady( ) object interpreterThread( ) void jediComplete_( object ) object jediThread( ) object libPath( ) void pythonInterpreterTimerAction( ) void runLineWithOptions_( object ) void runScriptWithFileAtPath_argv_( object, object ) void runScriptWithOptions_( object ) char running( ) void setInterpreterReady_( char ) void setInterpreterThread_( object ) void setJediThread_( object ) void setRunning_( char ) void setupInterpreterThreadRunLoop( ) void setupJediThreadRunLoop( ) void startInterpreter( ) void staticAnalysisForScript_completion_( object, @? ) void stop( )
@JonB To be honest, I'm not sure if I really want to expose this functionality via Python. I can see a couple of things that could go wrong, e.g. the console's implementation of
inputisn't really prepared for two interpreters running at the same time, and there are probably other issues that I'm not thinking of now.
You're right that
PA3PythonInterpreteris the one responsible for running Python 3.
PythonInterpreterhas a slightly different interface (for "historical reasons") and is Python 2-only.
runScriptWithFileAtPath_argv_is its primary method. The path should be a string, and the file should actually exist. argv can be nil/None, otherwise it's a list of strings (the script path is added to it implicitly). Most of the other stuff is internal, and shouldn't be called directly.
Edit: One more thing: You shouldn't try to instantiate any of the interpreter classes, they're essentially singletons, use
sharedInterpreter()to get the global instance.
Right. The main use case I think would be for stash-- to allow keeping the main codebase written in py2 without having to port everything to six, which has been iffy. on launch we'd maybe launch a worker thread in the py3 interpteter, and then py2 stash could send commands to the py3 worker when encountering a py3 shebang.
One bug I noticed is that when you press Tab in the console it will be converted to soaces, regardless of the 'soft-tabs' option.
Bug: when running a script via the url scheme (
pythonista3://) it ignores the default interpreter setting and runs the script as 3.5. It also ignores the shebang -
@omz, sorry another question about colliding betas so to speak. I seen yesterday we got a new thing (well for me it was new, a renew on the 2.x beta for 7 days , instead of an update in TestFlight). Great idea btw. Not sure if that's a new thing apple opened up to you or if it's been there all the time.
But if at anytime the 2.x beta is expired or not, if I delete it and install the App Store version will it just take the place of the beta leaving all my files intact?
Just want to make sure what will happen
@Phuket2 If you delete the app (tap and hold, then tap the delete icon) then your files will be deleted. If you install the App Store version over the beta, the data will probably stay in place, I don't think there were any major changes to Pythonista's data structure in the beta.
@dgelessus , ok thanks for that. I would have done it the wrong way and lost my data 😱 I should know better, but it appears I don't. Thanks again, makes sense
@omz - Just signed up for the beta, hope its not to late to test it out and provide feedback!
Hey, this topic just hit 20k views!
Seem to me the split-screen toggle is broken in the beta.
I had a full screen console and I could swipe left and right between it and the editor, then I pushed the split screen button and now swiping left/right transitions between either the editor with the file browser on the left or the editor with the (narrow) console on the right. Problem is, the split screen button seems to have disappeared now and I can't for the life of me figure out how to get the full screen console back.
Just went and checked in version 2 and the toggle remains after switching to split-screen. In the beta it disappears and only the help button remains at the top left of the console pane.
from objc_util import ObjCClass ObjCClass('NSUserDefaults').standardUserDefaults().setBool_forKey_(False, 'DockedAccessoriesPanel')
then restart the app
Any idea when the next beta will be, or better yet a release?
@JonB Thanks. I missed that post.
New beta literally fixes all the worst bugs, I'm so happy :D
- Improved console prompt: the text input area now expands automatically for multi-line statements
- Improved auto-indentation (also works when splitting a line now)
And also it also has most of my most-wanted editor features!
- Some improvements for external keyboard users 😍
- Experimental Today widget for running scripts in notification center
- Code completions can now be suggested based on fuzzy-matching
Thanks a lot, @omz, this is great work 👍