Python 3.0 rant >>> print 'Hello, World.' no longer works

Started by stumpy, June 15, 2009, 02:03:23 AM

Previous topic - Next topic

stumpy

I ordered a new computer a week and a half ago and it came in over the weekend. I remember a time when it was exciting and fun to set up a new system. Those days are long gone. Windows Vista will eventually be usable for me and I'll get past the silly OS design choices and UI frustrations. But, for now, it turns an experience that should have been a fun time breaking in a new toy into a tedious and annoying ordeal.

Anyway, not too long into the process, the time came to install Python. I actually have most all of my downloaded software and patches on a USB drive, so that I needn't track everything down when I need to reinstall, but I decided to go to python.org since the last version I installed on my older system was 2.5 and I knew that it was no longer current. At the site, I see they are up to 3.01 (3.1 due RSN). Woo hoo! Usually, each new version has had something I thought made it worthwhile and I was happy to have it. So, after all of my Vista sidegrade-with-no-functional-improvement-and-lots-of-pain vexation, I was looking forward to an actual upgrade with cool new stuff, right?

Maybe, maybe not. Python 3.0 is more of a mixed bag. There are some improvements (I like list comprehensions, the new .format() string method, etc.). But, it is deliberately backwards incompatible. As per my subject line, print 'Hello, World!' won't work. That means that whole libraries of pre-python 3.0 code will no longer work. filter() and map() no longer return lists. Neither does range(), btw. So, if you are quickly testing something and want to try
>>> range(9)
range(0, 9)

Very helpful.  <_< Okay, so, at least we can do
>>> list(range(9))
[0, 1, 2, 3, 4, 5, 6, 7, 8]

and
>>> range(9)[3]
still gives 3.

But, what about filter(), the handy way to apply a test to the items in a list and return a new list of the items that passed the test?
>>> test=filter(lambda x: x>4, range(9))
>>> test
<filter object at 0x03094DB0>

Oi! That is going to be annoying. A priciple benefit of an interpreted language is that it's easy for the human programmer to check intermediate results at the command line. So, surely the new filter class must have a decent human-readable string version that we can see by explicitly printing it...
>>> print test
Traceback (  File "<string>", line None
SyntaxError: invalid syntax (<interactive input>, line 1)

Groan! I can tell I am going to do that about a million times. Okay, getting with the print-is-a-function program
>>> print(test)
<filter object at 0x03094DB0>

Still no love. :angry: Maybe humans being able to understand code is less of a priority in the new Python. Anyway, I guess we are stuck with
>>> print(list(test))
[5, 6, 7, 8]

And, naturally, indexed access no longer works with the new object type. E.g.
>>> test[2]
Traceback (most recent call last):
 File "<interactive input>", line 1, in <module>
TypeError: 'filter' object is unsubscriptable


And, as we can see with that example, even many of the changes are language-lawyer "improvements" that make python more syntactically consistent, but not necessarily easier to use or easier to read. Part of the beauty of python is that it's both powerful and really easy to learn (relative to other programming languages). I am not a fan of Perl's haphazard "every syntax and the kitchen sink" approach, but it it's useful to have print statements stand out in code. It's worth a small sacrifice in consistency (print is obviously a function, so I can see the desire to treat it like one) to be able to quickly distinguish the parts of code that are doing some thinking and the parts that are printing results (often as debug code). Python hasn't generally been full of esoteric gobbledygook, but it's getting there with things like list comprehensions. I'm not saying we'll see the sort of shenanigans we see in C's for loops, but it's a step in that direction.

Are readability and easy-of-learning big deals? Well, frankly, YES. Most people who program (either as hobbyists or as professionals) don't use Python, so a language being easy to read and learn is huge. I had never used Python before, but when I looked into FF scripting a few years ago, my reaction was "Wow! You can do a lot with this language and be up and running in a hurry." I could recommend to a friend that s/he should consider Python for a project and suggest looking at some sample code, confident that they could read it and know what it does right away, which is a big selling point. Unlike, say, Perl, where I can barely understand my own code a year later and which one of my actual computer science (unlike me) friends refers to as "write-only" code, because it's so unreadable that you write it and hope you never have to look at it again.


Anyway, that's my rant. Not that Python is ruined now or anything, but I think this is a poor trend. And, for anyone who is dealing with an established code base (like all of us who do FF scripting), this could be a major hassle. So, are any coders planning to switch to Python 3.x? Frankly, I resisted the knee-jerk temptation to uninstall 3.0 and banish it from my system. Eventually, it might be useful.

But, a large chunk of my Python programming is game-related. Obviously, (and at the opposite end of the spectrum) Freedom Force coding will continue to be in Python 1.5.2. Because of that and the new incompatibility of Python 3.x, I can't even use the 3.x interpreters to prototype and debug my game code, because even basic things like print and filter don't work anymore and if I "update" the code in order to debug it in PythonWin or whatever, then it won't work in the game. :thumbdown:
Courage is knowing it might hurt, and doing it anyway. Stupidity is the same. And that's why life is hard. - Jeremy Goldberg

DrMike2000

Ouch!

Decisions like this absolutely mystify me.
To deliberately go and change the syntax of one of the most used commands (print) in the name of "consistency" is just arrogant and backwards.

I've always found that those who get a bee in their bonnet to change stuff arbitrarily due to some grand over-arching masterplan have louder voices than the pragamtic individuals who just want to get on with doing something with the language itself.

Me, I hate wasting energy on fixing things that arent broken.

Stranger Than Fiction:
The Strangers, Tales of the Navigator and Freedom Force X
www.fundamentzero.com

Epimethee

I have yet to try Python 3, because, IIRC, apart from better Unicode support, most of the real improvements are in the low-level infrastructure and won't matter until a few versions later. I think the Python Foundation itself doesn't see the 3.x series as a replacement for the 2.x for two or three years at the very least.

A good thing, because from your examples, yikes! the amount of basic elements changed or removed is not trivial. I had read about the print statement vs. function and about Guido van Rossum's dislike of map(), filter(), etc., but this looks like a major annoyance. And I can only agree with your point on readability (nice one about Perl, LOL), as the ease of learning and scalability from there is what got me into Python and coding (apart from some very basic JavaScript) in the first place.
FFX add-on for FFvsTTR at ffx.freedomforce4ever.com

stumpy

Quote from: DrMike2000 on June 15, 2009, 03:04:02 AMI've always found that those who get a bee in their bonnet to change stuff arbitrarily due to some grand over-arching masterplan have louder voices than the pragamtic individuals who just want to get on with doing something with the language itself.

Very true. I suppose programming language development is a microcosm of life, at least in that regard.

Quote from: Epimethee on June 15, 2009, 04:36:57 AMAnd I can only agree with your point on readability (nice one about Perl, LOL), as the ease of learning and scalability from there is what got me into Python and coding (apart from some very basic JavaScript) in the first place.

Yeah, and I think it's too easy for people who use the language all the time or who do a lot of programming to forget what a barrier it can be to new people who look at a pile of code and are tempted to just let other people do the programming. Sometimes easy-to-read is what keeps people hopeful that they can get going and do something cool without pounding their head on the wall. Any language where you can look at actual working code and easily understand what it does has an edge over the competition.

That's why I think print as a statement as opposed to a function is useful - it makes it easier to quickly parse where a bit of code is doing some thinking and where it's doing some talking. That's readability over syntactic purity. Readability is reason why most C programmers generally try to maintain some indentation in their code, even though there is no requirement for it in the language. By the Python 3 logic, why not have import be a function? Why have the keyword as a statement "wrapper" for what are obviously functions in the imp module? Heck, in Lisp and Scheme, even if, while, etc. are functions.


In fairness, though I don't like some of the changes, at least some effort was made to ease the pain. There is apparently a pretty full-featured translator that will do much of the work of porting existing code to Python 3. It doesn't help people (like us FF coders, and probably many others) who have to maintain a body of code in the earlier Python version for a wide variety of reasons...

I have particularly gotten used to the filter() and map() functions in FF because they are easy ways to do things that require both loops and testing in the single-line-at-a-time environment of the game console. Things like
MWs = lambda(lambda o: Object_GetTemplate(o)=='microwave', Mission_GetDynamicObjects())
Not that I would really mind
MWs = [o for o in Mission_GetDynamicObjects() if Object_GetTemplate(o)=='microwave']
But, of course, list comprehensions aren't available in the game.


BTW, as an aside, when I was installing Python on Vista, I spent some time to get it to install in the program files folder instead of in program files (x86), which is now the Micorsoft-approved home for 32-bit software. And, basically, I tried a couple times and gave up. since you can tell the installer that you are in one directory but it then does the install in another anyway. I tried copying over the files and changing the registry entries, but it seemed like Windows actually re-created the whole Python tree that I had in program files back in program files (x86). There are ways around this, but I really don't plan on stomping around the Windows registry all the time just to try and keep my program installations tidy.

Anyway, on a couple of these attempts, I thought I might have gotten it installed where I preferred and I wanted a simple check that the install was working and could find its stuff. My test was to to open PythonWin and import a module that isn't built into Python. Simple, no? The first one that came to mind was urllib2 (a high-level python module for opening and reading http traffic). So, I do the import and get "No module named urllib2" errors and I conclude that there is something fargled about the install. Okay, fine - it irks me to hew to this arbitrary Windows line, but I resign myself that this is one of those "choose your battles" moments where my energy would be better spent tilting at a windmill that has some functional consequence for me.

It wasn't until much later, when reading the Python 3 release notes, that I saw that urllib2 just happens to be one of the modules that no longer exists in Python 3. So, I may have actually had Python installed where I wanted it at some point, but I wouldn't have known because I managed to pick a test that would fail in Python 3 no matter what. :banghead:
Courage is knowing it might hurt, and doing it anyway. Stupidity is the same. And that's why life is hard. - Jeremy Goldberg