Planet London Python

May 21, 2015

Python Anywhere

PythonAnywhere's latest newsletter (ever)

Welcome to PythonAnywhere's latest newsletter. Latest not only because it's the most recent, but also because it's the most overdue!

Hi there fellow nerds! Another edition of our incredibly-rare-and-infrequent-newsletter (currently coming out about once a year).

First off, a late Christmas present announcement:

(No prizes for guessing when the first draft of this newsletter was composed.)

It's time for your Christmas present from PythonAnywhere. Can you guess what it is? That's right, we now support a new open source relational* database system, which is superior to the other one for a series of arcane technical reasons. Yay! We knew you'd like it.

And we've deployed the latest, shiniest version, 9.4, which includes that crazy JSONB stuff. You can check out our announcement about it here.

We had to wait until now to tell you because, um, we, er, well, anyway -- Postgres! Come on, Stonebraker got a Nobel prize for it, or something! Go check it out!

[*] And non-relational. Postgres like to claim they do pretty well at the whole NoSQL thing, what with being able to work with JSON data both faster and more reliably than MongoDB.

Customise your account

Towards the end of last year we introduced the idea of a "custom" plan, where you can choose exactly the amount of CPU-seconds, web applications & workers, and gigs of storage you want on your account, and so only pay for what you need. We've now made it so that all plans are customisable from the get-go. So if you ever felt like adding Postgres to your plan (yep, you have to pay for it 'mafraid), or just giving yourself a couple of gigs of extra space, or even (whisper it) slightly reducing the features on your account to save money, then you can now do that with total impunity.

Custom plan settings

PythonAnywhere in education

We've had lots of students and teachers on PythonAnywhere over the years, happy to save themselves from the installation hassles of getting Python onto a disparate bunch of hardware, and happy in a place where the batteries are included and the experience is consistent. And since the world seems to be agreeing that everyone should know the basics of coding, and that Python is the language to do it in, we thought we'd see what we can do to help. So, if you or your friends are teaching Python, you can read more about it here and get in touch with us here. We'd love to get you on board and see if we can help :-)

Now for some Easter eggs :)

(No prizes for guessing when we had a second, abortive, stab at writing this newsletter. Honestly, it's as if we enjoy writing code more than we enjoy writing marketing emails.)

Forget about Christmas presents, how about some Easter eggs? Yeah, that's totally still topical. Is your world-conquering startup in stealth mode? Or just shy? Either way, you'll like the option the put HTTP auth on your site, and hide it away from prying eyes. Want to know what's running in your consoles? Check out the process listing on the consoles page, to help you track down what job is sucking up all your precious CPU quota. Speaking of which we've boosted the features of base accounts so y'all get a few more seconds and gigs from all of us. Check the new pricing page for details. We've also been serving the live consoles on, we've improved virtualenv support for web apps, and lots more.

Blog posts

We've published some fun stuff here on the blog recently, here are some of our favourites:

And that's it! Until next time (next scheduled newsletter: mid-summer 2015. Expected arrival time: may need 5-digits for the year on your calendar).

by harry at May 21, 2015 11:55 AM

May 20, 2015

Steve Holden

What Kind of Geek am I? (1)

I've been pondering about why sometimes progress seems hard to make when I am learning a new piece of technology, which other people apparently just pick up and start using with no trouble at all. I now wonder whether it's a combination of personality and knowledge.

In common with many developers I like to understand things thoroughly. For me this means being able to construct satisfactorily self-consistent mental models that I can, effectively, "unit test" by applying what-if techniques. Unfortunately my history as a developer means that I have a detailed knowledge of system architecture. Without claiming to be fully up-to-date (for example the last time I built logic was in 1987, from Schottky TTL clocked at 12 MHz), when I use the term "full-stack" I include a reasonably detailed knowledge of all aspects of system architecture, including the hardware, operating system, language support libraries and application.

In other words, I am (often subconsciously, thanks to many more than 10,000 hours of practice at this computer game) aware of lots of things that can go wrong at many different levels.

I suspect this causes me, without specific motivation, to choose test cases that go “near the edge of the envelope”. It's frustrating when I'm learning because it often reveals deficiencies (most often in the documentation) of the “system under test” that can block progress; but I also believe it helps to integrate my newly-learned knowledge, and leaves me with valuable knowledge that you just can't pick up in the middle of the road.

by Steve ( at May 20, 2015 06:08 AM

May 14, 2015

Peter Bengtsson

Python slow-down of exception handling or condition checking

It's the old problem of "Do I seek permission or ask for forgiveness?". It's rarely easy to know which one to use in Python because working with exceptions in Python is so damn easy.

Generally I prefer neither. I.e. just do. Don't write defensive code if you don't have to. Only seek permission or ask for forgiveness if you expect it to happen and that that's normal.

Consider the following three functions:

def f0(x):
    return PI / x

def f1(x):
    if x != 0:
        return PI / x
        return -1

def f2(x):
        return PI / x
    except ZeroDivisionError:
        return -1

Which one do you think is the fastest? If I run this 1,000,000 times and never pass in a value for x=0 will it make any difference?

Before you look at it, what do you think the result will be?

The answer is below.

Read on.

Scroll down for the results.

Have you made a guess yet?

What do you think it's going to be?

Scroll some more.

Almost there!

Ok, the results are as follows when running each of the above mentioned functions ~33,000,000 times on my MacBook:

f0 4.16087803245
f1 4.84187698364
f2 4.73760977387
(smaller is better)

Conclusion, the difference is miniscule. The fastest is to not do any exception handling or condition checking but it's generally no big difference.

This test was done with Python 2.7.9. You can try the code for yourself.

Just one more thought

As I wrote this post I started thinking more and more about the "code style aspect" rather than the performance.

Basically, I think it boils down to the following rules:

  1. If you're working with external I/O (e.g. network or a database) use the "ask for forgiveness" approach (aka. exception wrapping). I.e. don't do if requests.head(url).status_code == 200: stuff = requests.get(url)

  2. If you want to make a really user-friendly Python API, use the "seek permission" approach (aka. if-statement first). E.g. def calculate(guests): if isinstance(guests, basestring): guests = [guests]

  3. All else just do. That makes the code more Pythonic. If you have a sub-routine that sends in variable of the totally crazy-wrong type to your function, don't change the function, change the sub-routine.


Here are the numbers for PyPy:

f0 0.369750552707
f1 0.321069081624
f2 0.411438703537
(smaller is better)

That's after averaging 15 runs of the script.

Note that the function with the extra if statement is faster.

And here are the numbers of Python 3.4.2:

f0 4.99579153742
f1 5.77459328515
f2 5.38382162367
(smaller is better)

That's averaging 10 rounds.

One almost interesting thing about these numbers is that the sum of them are different and tells us a tiny story about performance for the language:

Python 2.7.9   13.74036478996
PyPy 2.4.0     1.102258337868
Python 3.4.2   16.15420644624
(smaller is better)


Here's the node equivalent version and its times:

f0 0.215509441
f1 0.228280196357
f2 0.316222934714
(smaller is better)

That means that my Node v0.10.35 is 45% faster than PyPy. But please, don't take that seriously.

May 14, 2015 09:50 PM