Thursday, November 13, 2008

Pydev & Python 3.0

One thing that should be added in the next release is support for Python 3.0 (aka Python 3k)

So, to cover that, I've started at the most basic part: being able to configure an interpreter with Python 3.0. And you guessed it: print does not work anymore, so, when I started checking how can support be added for Python 3.0 while still retaining compatibility with other versions (as most existent python library probably will have to do), something weird struck me: print is now something banned in the python world...

Not only won't I be able to use the print statement (because it's not available on Python 3.0), but I also won't be able to use the print function (because it's not available in older versions of Python), so, when considering the 2to3 tool, actually, what should be available is a 2toAny, where print is removed altogether in what's probably going to be the actual standard for python: instead of print 'x', the thing to have backward compatibility is writing: sys.stdout.write('x\n') -- which I think is really something sad -- probably a step backwards for python, where printing something used to be sane... unlike java things such as System.out.println()... But now not only it's very similar -- it also gets worse: you have to add the new line yourself.

So, in the 2toAny, what should be done is transforming print varA into sys.stdout.write('%s\n' % (varA,)) and print >> log, varA into log.write('%s\n', (varA,))-- much more pythonic right?!?

Well, aside from that, I wanted to say that besides that particular change, most other things seem to be consistent in taking the language forward... but that one seems just gratuitous breakage of most python code existent (it's not like print is used seldonly in the python world or anyone did actually dislike it).

I'm sorry about the tone of this post, but I must say I'm a bit disapointed with that particular change in Python at this stage... Am I missing something here? Is there another way to really have actual compatibility? -- Maybe defining my own print_ function and using it everywhere? Why did Python "fix" something that not only worked, but that everyone was happy about? (or wasn't?)

How about a python 2toAny tool, does someone know if such a thing exists? It's probably much more important than a 2to3 (as almost all libraries will need to keep supporting old versions and probably only few projects will actually migrate to 3.0 -- at least initially and until the libraries they use are able to support it).

11 comments:

manuelg said...

3toAny2 is what is missing

Python 3 will be the most "expressive" version of Python, having straightforward and correct ways to write most tasks (especially i18n, and playing with strings of bytes)

I would wait until Python 3 is ready (or, if you wish, support Python 3 exclusively through 2to3)

When Python 3 becomes the preferred way to code, the community will have to make 3toAny2 tools, out of necessity.

manuelg said...

Steve Holden has a very nice write-up about the "Python 3 Blues"

http://holdenweb.blogspot.com/2008/11/dont-use-python-30-really.html

Anonymous said...

I fully agree with this post !

I always used to start introduction to Python for scientists by "No worries, it's a scalable language, no need for a blunt 'public static void main' right from the the start, just 'print "Hello world !"' will do it at the beginning.

Then you'll see the language will scale up with your needs/skills to a full blown OO language that can achieve almost anything you can think of.

On my side, I guess I'll hack the interpreter to re-introduce print before deployment to my users...

Daniel Lindsley said...

You should be able to import the next print function from the "__future__" module. There's also a command-line switch ('-3') to enable Python 3.0 compatibility testing.

Documentation is at http://docs.python.org/whatsnew/2.6.html#pep-3105-print-as-a-function as well as http://docs.python.org/library/future_builtins.html.

pantsgolem said...

I don't think I follow. Python 3 source files won't run in a Python 2 interpreter, but that's the entire point. How is the print function different than any of the other backwards-incompatible changes?

chphilli said...

I think the thing to note here is that, for the most part, libraries shouldn't be using print anyways. In my opinion, print (whether as a statement, or as a function) is reserved as an application level tool.

Instead, libraries should be using the logging module, which allows the application that uses it to determine exactly how and where they want the output to be formatted. As an application developer, a library using the print statement mucks with my intended output, leaving me with little options to deal with the problem.

That said, I've been there -- you're working on a library class, using print to debug and then eventually realize that you need to convert all those statements to logging calls -- oops! The nice thing about the new syntax is that I don't have to do that anymore. When I'm ready, I just locally replace the print function with a function that redirects to logging and I'm done.

I haven't looked into PyDev itself, so I'm not sure how much this will affect you -- since you're using the interpreter, don't you get these differences (mostly) for free? If I configure a project I wrote in 3.0-syntax to use a 2.x interpreter, it should fail.

Dobes said...

I haven't looked to closely at this, but if python3k uses a print() function, couldn't you make code forward compatible by putting parens around your string, like this:

C:\Users\dobes>python
>>> print ('this is a test')
this is a test

Since print is used only for debugging 99% of the time, this is probably a reasonable solution for most people using print currently.

Fabio Zadrozny said...

Just to say my specific case for using print (or at least needing the output on stdout):

1. To configure the interpreter there's a python script that's run with the selected interpreter to gather info from it (builtins, version and pythonpath), so, supporting all the python versions is a necessity in this case, and, the from __future__ import print_function won't work... (on older versions)

2. Tracing calls, debugging calls, and I need to support some modified versions of xml-rpc (to support old versions) that gave prints... and (until now) the single thing that broke it is that it used print.

Is really changing the print statement to a logging call really something that was difficult to do? I never got such a request (or that impression) for Pydev... If that was really so difficult, certainly having something in your environment to change the print statement to a log call would be better than breaking the language at that level... (although, now that this is becoming something forced from the python world... changing print to sys.stdout.write is a real necessity)

@pantsgolem: I think it's different because that used to be something used extensively and I believe most people would say that it's support was extremely good (and now print cannot be used in any python version for anyone that needs to support more than 1 version)

@chphilli: Changes in the grammar don't come for free for Pydev -- it uses its own grammar, which is actually a forked and enhanced version of the jython grammar, so, I have to go on and update it to support grammar changes (but it goes on par with any grammar change, so, that's something really expected and it's not really a concern at that level)

ltbarcly said...

Python is a *dynamic* language.

Conditionally define a print function that works like the python 3.0 print function, then use that. In the event that the actual python 3.0 print function is available, your new def print isn't evaluated, so done and done.

This is just the same thing we have been doing for years, like how you had ot do try: from Set import set.

Fabio Zadrozny said...

Actually, you can't define a print function... (at least not the same name), but you could define another function (say prn) to do it and use it everywhere (maybe put it in the builtins), but the name print is banned for supporting python 2 and 3 (note that I'm not saying that it cannot be done, it's just that the actual print name should be something considered banned for anyone interested in supporting python 2 and 3)

Anonymous said...

I guess I'm missing something here. Why are trying to make a single Pydev lib that works in 2.x and 3.x??

Fork it already