Back to school tips for teachers, from PythonAnywhere

Dear teachers,

If there's one thing we know, it's that teachers (and students) love, it's being reminded that the holidays is that the holidays are coming to an end. Hooray!

Here's a few ideas and pointers for some of the things that we hope will make your life, as a teacher, easier.

1. PythonAnywhere means all your students have exactly the same setup

If you're already a PythonAnywhere user, you'll already know this. But, any teacher that's struggled with getting several different students, with different hardware and operating systems, all set up and working for a basic programming class, know how much time is easily lost.

With PythonAnywhere, everyone has the same kind of terminal, the same operating system, the same versions of Python, and the same standard installation. And you can jump on and view exactly what your students are doing.

2. PythonAnywhere makes it easy to go beyond the basics, and use external libraries

We have hundreds of packages preinstalled, and it's easy to install new ones. Here's a few examples of packages, and the associated topic which you could build a lesson around:

  • Scraping with requests and beautiful soup
  • Accessing the google maps api with google-api-python-client
  • Number crunching with numpy/pandas/scipy/scikit-learn
  • Use sqlalchemy to access our provided mysql/postgres databases
  • Best practices such as version control and isolated environments with git/mercurial/virtualenv
  • Python standard library modules such as sqlite3, unittest, re, pickle, pdb

Here's our full list of preinstalled "batteries included"

And here are our instructions for installing new modules

3. PythonAnywhere makes it easy to distribute and collect assignments from your students.

Because all your students' home directories are available to you in a Bash console, it's easy to copy files from your accounts to theirs, and back again. Check out the worked example on our help page.

Once you've got the basic idea, your imagination is the only constraint on what you could achieve by building little automated scripts to help your classes. Off the top of our non-teacher heads, how about:

  • Checking last updated times, and counting line numbers, in assignments files, to see who's been working and who hasn't

  • Writing a scheduled task to copy assignments across to your own folder at a pre-specified time, thus automating the "deadline" for the assignment

  • Automatically running student scripts and emailing yourself the results, possibly even grading assignments automatically.

If any of that piques your curiosity but you're not quite sure how to go about it, don't hesitate to get in touch, and we'll happily point you in the right direction.

4. PythonAnywhere makes it really easy for your students to build a real, publicly available website

You can use python web frameworks such as django, flask, bottle or web2py while we take care of the infrastructure behind it. No need to worry about server configuration, load balancing, or keeping the operating system patched - we take care of all that for you.

5. We recently introduced Jupyter Notebook support (aka IPython notebook).

These are interactive "notebooks" that let you run bits of code step by step and get instant feedback. It allows you to include explanatory text and data visualizations directly in the notebook and is used by university researchers worldwide.

Many teachers have told us they love the interactive nature of notebooks, with the easy ability to "go back", change things, and see the effect filter down -- something that really helps students with exploratory coding.

Unfortunately notebooks are currently a premium feature, but (read on...)

6. We can create a custom "teacher" plan for you, if you need some paid features for your students.

Currently, free accounts have certain restrictions:

  • Internet access is restricted to a whitelist of sites (

  • You cannot use SSH, and your disk & CPU quota is limited

  • You cannot use Jupyter Notebooks

  • You cannot host applications on custom domains (only

However, we have started offering special pricing for teachers, whereby we can lift one or many of the above restrictions, for $1/student/month. Get in touch with us and we'll help you out.

7. You can create your own step-by-step tutorial, integrated into the PythonAnywhere UI.

Ever used one of our little green "tutorials", the step-by-step instructions that sit in green boxes at the top of a pythonanywhere screen?

They're actually open-source, and you can write your own, for your students to use, and we'll integrate it into PythonAnywhere. Get in touch for more information.

That's our top seven, but there's many more little things that (we hope) will make life for teachers easier:

  • You can work on the go from your tablet/ipad
  • We can do bulk creation of accounts for all the students in your class in one go.
  • We can also set up special "exam" accounts, for you to use in test situations, or controlled assessments.

We're always keen to go the extra mile to make sure teachers and students are getting the best out of PythonAnywhere, so don't hesitate to email us, and let us know what you're doing, and how we can help.

Latest deploy: new stylings, editor fixes, and our API beta

Morning all! A lovely day for leave-ing an old server image behind and welcoming in a new, independent, codebase. #brupgrade #brelease #breployment.

Style tweaks, improvements to responsiveness

On a bit of a whim we decided to upgrade to bootstrap 3, so you'll notice slightly different stylings. Flat buttons! Oh-so-3-years-ago. But also, there are some improvements to the way the site displays on mobile and smaller displays, which is nice.

We also upgraded to the latest version of the ace editor, which should bring a few little improvements too, like better vim keybindings, and better support for ipads (you can now scroll, yay!)

API beta

It's not ready for prime-time yet, but we've started work on a PythonAnywhere API. It may end up not being something we publish for general use, and just something for us to use behind the scenes, but if you're keen to take a look, get in touch, and we'll switch it on for you. Currently the API allows you to do stuff to your web apps, namely:

  • create new web app
  • reload web app
  • update webapp settings: virtualenv, static files.

You should bear in mind that anything you build using that api will probably break when we next do a release, we're making no guarantees about backward-compatibility, or that the api will even work as it is. So really it's just for playing around or for the curious for now. Still, email us if you're interested, we'd love to hear from you.

Other changes

  • There's now a UI for updating the working directory and source files location for your web apps.
  • The editor now gives you a useful warning when you try and save if you're over your quota (and it no longer deletes your whole file, which some consider a bonus)
  • We've made some changes to try and make it easier for us to deal with forum spam. ugh.
  • and a few assorted minor bugfixes.

Your comments and suggestions are always welcome. Enjoy!

The PythonAnywhere newsletter, June 2016

Summer is just around the corner in the northern hemisphere -- here in London we can tell because the rain is just that little bit warmer. We're taking full advantage of the lighter and later grey in the sky by working even longer hours to make PythonAnywhere better. How? Just read on...

Better databases!

Over a year ago, we started supporting Postgres databases. Since then, we've found that we've been able to optimise the service so that it scales better than we thought, so we're pleased to pass on the cost savings to you.

Postgres is now $7/month instead of $15, so if you've ever thought about checking it out but been put off by the price, now's the time to take a look!

We've also applied the new price to existing Postgres users for their next bill. So that's more moolah in your pockets dear users, don't spend it all at once ;)

Also -- the way we handle MySQL databases needed some work to make it faster, more efficient, and more scalable. Over the last month we've learned more about obscure aspects of database administration than we ever wanted to know... but the end result for you should be that your database access is faster and smoother. Let us know how it's going!

Useful tips and interesting ideas

The inside scoop from our forums

New modules

Although you can install Python packages on PythonAnywhere yourself, we like to make sure that we have plenty of batteries included.

We haven't added any new ones since our last newsletter :-( -- but we've got a bunch in the pipeline -- more next time!

New whitelisted sites

Paying PythonAnywhere customers get unrestricted Internet access, but if you're a free PythonAnywhere user, you may have hit problems when writing code that tries to access sites elsewhere on the Internet. We have to restrict you to sites on a whitelist to stop hackers from creating dummy accounts to hide their identities when breaking into other people's websites.

But we really do encourage you to suggest new sites that should be on the whitelist. Our rule is, if it's got an official public API, which means that the site's owners are encouraging automated access to their server, then we'll whitelist it.

Here are some sites we've added since our last newsletter:

  • and -- the Internet Archive!
  • and -- If This Then That
  • * -- "the easiest way to map and analyze your location data"
  • -- Blockchain web services
  • -- more Bitcoin goodness
  • -- a geographical database
  • and -- APIs for human resources applications
  • -- enterprise messaging
  • -- an API for digging up information about IP addresses
  • -- a GoDaddy service for posting your details to aggregators like Google, Yelp, and so on.
  • -- parcel tracking
  • -- phone and text APIs
  • -- a recipe site
  • -- Chicago Transit Authority

And that's it

Thanks for reading our newsletter! Tune in the same time next month (ish) for more news from PythonAnywhere.

Today's upgrade - postgres price drop, mysql scaling improvements

Nothing earth-shattering to report today, but some good news:

Postgres is cheaper

It's been over a year since we first tentatively launched our postgres service, and we've found that we're able to optimise the service so that it scales better than we thought, so we're pleased to pass on the cost savings to you.

Postgres is now $7/month instead of $15. That price will apply to all new plans and upgrades, and we'll also start applying the new price to existing users for their next bill. So that more moolah in your pockets dear users, don't spend it all at once ;)

MySQL infrastructure changes

These changes won't really be very visible from the user point of view, so this isn't very interesting to you, beloved readers, per se, but it took us loads of time and effort so we have to say something to make it all feel worthwhile and satisfy our own egos. Anyways, we made some changes to the way we shard users amongst MySQL servers in our clusters, which mean it's now much easier for us to add extra MySQL capacity whenever we want to.

For the curious, did you know that (depending on your OS and config), filesystem limits on the number of hard links in a single directory might limit you to a maximum of 32,000 databases on a single mysql instance? Not that we ever came anywhere near that, but still, good to know. #tipsforpaasproviders. console now Python 3.5

Our live consoles on the front page are now Python 3.5 instead of 3.4. We've also made them "regular" Python consoles instead of IPython (which was always a slightly weird decision, even though IPython is all awesome and everything, but a regular Python console is what new users are most likely to see, and ours do have tab-completion switched on you know?)

Onwards and upwards folks! In our next iteration we hope to be able to release a first beta of an API for PythonAnywhere. Watch this space :)

Scaling a startup from side project to 20 million hits/month - an interview with creator Kaustubh

We recently wished farewell to a customer who had been with us for about 18 months, during which time he saw some incredible growth in what was originally just a side project. We spoke to him about how he found the experience of scaling on PythonAnywhere, and why he decided to move on. stats
Project started:October 2014
Requests:20 million / month
Active users:1000+

What's your background? How long have you been programming?

I am currently pursuing Bachelor's in Computer Science & Engineering. I have been programming from school days but RailwayAPI was the first substantial project I did.

Can you describe what does? What first gave you the idea to build a site like this?

It all started with an idea to build an app which let Train travelers in India find the best available route between two stations. It's very difficult to get confirmed bookings in India and so I thought it would be great if there was an app which helps people break their journey up, using multiple trains to reach their destination in minimum time.

While working on that idea I realized that I needed train data to make such a thing possible. There wasn't a reliable API for Indian railways and I realized that several developers would be facing the same problem. And hence RailwayAPI was born.

It is a collection of APIs which let developers access all kinds of Railway data like Seat Availability, Train Route, Live Train status etc in easy-to-use JSON formats.

Why did you choose Python and Flask? Are you happy with your choice?

Python was the language I already knew well and there were several great libraries available for it so the decision was very easy to make for me.

Since the exposed part of the API was just going to be URL views which capture GET requests and return the corresponding JSON, Flask was the most suitable with its minimality which is enough for what I was doing.

What made you choose PythonAnywhere?

This was my first webapp and initially I had very little experience in setting up such an environment. After some research I stumbled upon PythonAnywhere which was extremely easy to set up, with a nice and clean UI. It also lets you instantly scale up your app by just sliding the number of workers you are going to need. After that I needn't go anywhere else!

Your site quickly became one of our busiest sites -- when did you realise it was getting big? How was the experience of scaling up on PythonAnywhere?

I realized that it was getting big when one of the user complained about load balancer errors they were getting. But it wasn't an issue as I quickly scaled up the number of workers and site was back to normal functioning in seconds.

What kind of traffic did you have last month, for example?

The site got about 19.6 million requests last month! And for the month before that it was about 16 million requests.

You've now decided to move on -- why is that, where did you move to, and was it easy to make the transition?

Yes, I have moved to a VPS now at Digital Ocean. It wasn't an easy decision to make for me and it was done only after considerable thought. I loved PythonAnywhere and I continue to love it but I needed more flexible configurations so a VPS was required at the current stage.

It was quite difficult to move to a VPS because I have grown accustomed with the ease of use at PythonAnywhere where everything is pre set up and you can just focus on writing your code instead of writing configurations.

In general, what do you think are the pros and cons of PythonAnywhere?

I think I have already mentioned a lot of Pros about PythonAnywhere. But in short if you just want to focus on building your app rather than setting up environment, which is what ideally it should be than there are very few places like PythonAnywhere out there. Also developers should know that setting up an environment is not a one off process, it requires constant monitoring and changes so that any modification in the code doesn't break the configuration and vice versa. Its quite a time consuming process but PythonAnywhere takes care of all of that.

I would have liked it if PA supported asynchronous workers. In fact this was the main reason for moving out because my application was Network I/O bound and async workers were better suited for such a task, and that wasn't available here, at least for now.

Also it would be great if Redis and Web Sockets were also supported at some point.

It sounds like the site was a big success. What's next for

The goal is to give developers access to Indian Railways data without hassle. There are some other ideas I am working on like making available Train and Seat Availability prediction/analytics through API.

Do you have any advice for other aspiring web developers?

I am still learning a lot myself!

Although I could say from my experience that the most important thing I learned while developing the API was that engineering your App to be scalable is one the most challenging tasks, which is often overlooked by people in the beginning.

I had to re-code several of the modules several times because they resembled 'hacky' code but as the pressure on the site grew they started to break. So it would be good if developers also think about how their app would respond to such scenarios in the future.

Thanks again Kaustubh, and best of luck with the future of the project!

Anatomy of a bug

We recently fixed a problem in our website hosting code that was causing weird errors under very specific and rare circumstances. The problem had been there for several years, and -- while we knew that odd stuff happened every now and then -- we'd never been able to reproduce it reliably enough to debug it. But a lucky coincidence of circumstances, when two people tripped over the bug in quick succession, clarified the issues and let us work out the solution. It's an interesting tale, so we thought we'd share it.

The problem

Every now and then -- say, once every six months -- someone would report that they had a Flask website which would inexplicably start returning CSRF errors for every request. The apps in question generally had CSRF protection disabled. The error messages were very generic -- there was no indication of where in the stack they came from. And the problem would go away if the web app was reloaded.

There was no obvious pattern that we could see, apart from the fact that it was always Flask apps. No bugs had been reported against Flask's CSRF protection plugins.

We couldn't for the life of us work out what was causing the problem. Our normal request-processing stack (two layers of nginx for loadbalancing and basic HTTP(S), then uWSGI) doesn't do any CSRF-related stuff, and it sends all headers and requests through unchanged. But no-one else was seeing this problem on other hosts, so it seemed likely that there was something odd going on with our service specifically.

The lucky coincidence

Two things happened: we recently upgraded the version of Django that we use to host the PythonAnywhere website itself to 1.9 (from an embarassingly old version that I won't mention). And then, two people reported the weird CSRF problems in quick succession. One was using Flask, but the other was using Django. So maybe the problem wasn't Flask-specific.

Even more interestingly, they were both getting exactly the same error message -- and it was slightly different to the one that had been coming back before. Furthermore it was one that, on Googling, we could only find in newer versions of the Django codebase. This sounded suspiciously like it was coming from somewhere in our infrastructure -- it had changed when we upgraded, and it was a Django message even for the Flask app. But why would our code -- the Django code that makes up the PythonAnywhere website -- be called when a request was being made to one of our customers' sites?

Website wakeup

PythonAnywhere's web hosting platform is made up of a large number of web servers. Each web server is capable of serving any of the tens of thousands of websites we host. But, of course, the code for only a subset of those sites is running on any given server at any given time. We load-balance across the web servers, sending the traffic for each hosted site to a specific server. If we add another web server when things are busy, it's a simple job to tell the loadbalancer to spread the traffic out differently, so that the new server takes over handling some of the sites.

If one of our webservers gets a request for a website that isn't already running on it, the request gets redirected internally to a view on a PythonAnywhere web app, which checks to make sure that the site is one that we're actually meant to be hosting (rather than some random domain that someone happens to have pointed at one of our IP addresses). If it is, it starts the site up and redirects the incoming request back round again internally to the original URL. Once that's happened, the requester gets the response from the freshly-started website.

This means that when we add a new server, which will be running no websites initially, it will start them up one by one as it receives the first request for each from the loadbalancer.


Once we'd realised that the error that was coming back for our customers' sites was from Django, and had changed when we upgraded Django, it was clear that this "wake up" view in our own code was the only possible culprit. It's the only bit of our code that would ever be run in response to a request for a customer site.

We took a look at the view -- and, it turned out, it wasn't marked as CSRF exempt. Why does that matter?

We use CSRF heavily across our site (to mitigate the risk of a malicious person putting up a website that posted a "delete my web app" request to PythonAnywhere when someone visited it), and CSRF protection is the default -- each view must explicitly opt-out.

Now, "wake up" requests to this view would come in without any CSRF tokens or other related data. CSRF is site-specific, and the wake-up requests were not really requests for our site at all -- they were requests meant for another site that had been temporarily passed over to us so that we could start up the code to handle them.

So it was definitely a bug that the view wasn't marked CSRF exempt.

Importantly, though, CSRF protection is only relevant to POST requests. GET requests don't need it, as they are (so long as you're doing things properly) not state-changing operations.

So we'd worked out part of the problem -- if a website wasn't running on a given server, and a request for that site was sent to the server, then only a GET request would start the site correctly. A POST request would get a spurious CSRF error, and the site would not be started up.

But our customers who had reported the problem were saying that when their websites got into the CSRF-error state, they'd stay in that state regardless of how much traffic they got. And also, what was the Flask connection? While we now had one person seeing the problem with Django, every other report had been against Flask.

Finally, one of our customers who was having the problem told us something that made it all clear. He explained that his site was collecting data from other computers elsewhere on the Internet, which were only ever POSTing to it. He had discovered that when it got into the state when it was always responding with CSRF errors, he didn't need to reload it to fix it. He just needed to log in to the admin page.

Suddenly it all became clear. The lack of the @csrf_exempt decorator on our "wake up the website" view meant that it would always respond to a POST request with a CSRF error. But if it received a GET request (for example, a hit from a browser on the admin login page, or a manual reload from the "Web" tab on PythonAnywhere), it would work properly and start the website. Once that had happened, then all further POST requests would work.

Types of websites

This taught us something interesting about the kind of sites people build. There are two main kinds of sites on PythonAnywhere (and we think on the Internet at large) -- human-readable and computer-readable.

Human-readable sites get a lot of GET requests as people hit them and browse around looking at pictures of cats. They get the occasional POST as someone comments on a cat picture, or sends a message to the cat or its owner, but most hits are GETs.

Computer-readable sites are basically web APIs. They also get quite a few GETs. But sometimes, they're designed to get mostly POSTs. The data-collection site that our customer was building, for example. Or sites that exist entirely to receive webhook messages.

Most of the sites on PythonAnywhere are human-readable, but there are a fair number of computer-readable ones. Of the computer-readable ones, most get a decent number of GET requests. A tiny proportion are APIs that get predominantly POSTs. So while every site on PythonAnywhere would have the problem where it couldn't be woken up by a POST request, only a very small subset of them would be seriously affected -- the ones that got almost nothing but POSTs.

The problem was only affecting that tiny proportion of sites. But the fact that their sites were only handling POSTs wasn't something that was obviously relevant information to the customers who were reporting the problem, so they didn't mention it. And because we didn't know what the cause was, we never knew that it was something we should ask about.

And the Flask connection? Well, if you're building a website that handles lots of POST requests, and you don't need to worry about user management, administration, and user interface design, which framework are you most likely to pick? Flask is almost certainly the most popular framework for people building simple web APIs. So it wasn't quite a red herring that the problem seemed originally to be Flask-specific -- there was a very strong correlation there -- but that correlation really did mislead us into thinking it was some weird interaction with Flask specifically.

The fix

Once we knew what the problem was, it was trivial to fix -- just adding a @csrf_exempt on the correct view -- and we had it patched within an hour, even including testing.

But it was a long and confusing year puzzling over the issue! Hopefully the explanation gives some flavour of the sleuthing process.

The PythonAnywhere newsletter, April 2016

Spring is here, we're filled with good intentions, and here is another newsletter, almost exactly a month after the previous one, which is 800% better than our previous interval.

So other than good intentions, clock changes, and eating too much chocolate, what's been going on? Plenty of stuff it turns out, and it's all for you, dear users:

PythonAnywhere now supports Python 3.5

Python 3.5 has been out of beta since last summer, and in the end we figured that if we wanted to preserve any self-respect whatsoever, it was time to make it available on PythonAnywhere.

You can now use Python 3.5 in web apps, consoles and scheduled tasks. And IPython Notebooks too if you're a paying user!

Python 3.5 in and of itself isn't that exciting -- there's a bunch of syntactic sugar for asyncio (which we don't support for web apps however), there's a matrix multiplication operator, @, which might be useful for a niche audience, and a few nice bugfixes and extensions in pathlib and subprocess and elsewhere:

Here are the official Python 3.5 release notes.

But one of the nice side-effects was that we got to install a fresh stack of packages, so the default version of Django is 1.9 in Python 3.5, and it also has the latest version of requests, and so on. More info on the "batteries included" page.

But you should probably still use a virtualenv for your web apps!

The inside scoop on our forums

Useful tips

New modules

Although you can install Python packages on PythonAnywhere yourself, we like to make sure that we have plenty of batteries included. Here's what we've added since the last newsletter:

Python 3.5

It's new, so we've added all of the packages that we previously supported for Python 3.4 and 3.3. We've installed the most recent versions we could get, though, so many of them are more up-to-date. Django 1.9.3 FTW!

Python 2.7, 3.3 and 3.4

  • pyodbc and its lower-level dependencies, so you should be able to connect to Microsoft SQL Servers elsewhere on the Internet.
  • pypdftk and its dependencies -- now we have three separate PDF libraries!
  • pint
  • uncertainties
  • flask-openid
  • And finally, we've upgraded twilio so that it works properly from free accounts.

Python 3.3 and 3.4 specific

  • mysqlclient (so now Django should work out of the box with Python 3)
  • basemap

New whitelisted sites

Paying PythonAnywhere customers get unrestricted Internet access, but if you're a free PythonAnywhere user, you may have hit problems when writing code that tries to access sites elsewhere on the Internet. We have to restrict you to sites on a whitelist to stop hackers from creating dummy accounts to hide their identities when breaking into other people's websites.

But we really do encourage you to suggest new sites that should be on the whitelist. Our rule is, if it's got an official public API, which means that the site's owners are encouraging automated access to their server, then we'll whitelist it.

Here are some sites we've added since our last newsletter:

  • * -- like you'd expect, Wikipedia's database.
  • -- speech-to-text
  • * and * so that GoLang developers can run stuff on PythonAnywhree
  • -- a translation platform
  • -- a site to push business listings to a variety of directories
  • -- manage RSS feeds
  • -- a protein interaction database
  • -- exactly what you think it is, unless you're in the US -- it's about soccer.
  • -- API for the FX rates published by the European Central Bank
  • -- a Norwegian banking site.
  • -- hockey stats
  • -- various endpoints for one of China's biggest sites
  • -- German transport data
  • and -- Dropbox for the enterprise
  • * -- MongoLab's new name
  • -- an online database of places to meet for dates.
  • -- an identity API

And that's it

Thanks for reading our newsletter! Tune in the same time next month for more news from PythonAnywhere.

System upgrade, 2016-04-12: Python 3.5

We upgraded PythonAnywhere today. The big story for this release is that we now support Python 3.5.1 everywhere :-) We've put it through extensive testing, but of course it's possible that glitches remain -- please do let us know in the forums or by email if you find any.

There were a few other minor changes -- basically, a bunch of system package installs and upgrades:

  • mysqlclient for Python 3.x (so now Django should work out of the box with Python 3)
  • pyodbc and its lower-level dependencies, so you should be able to connect to Microsoft SQL Servers elsewhere on the Internet.
  • pdftk
  • basemap for Python 3.x.
  • pint
  • uncertainties
  • flask-openid
  • And finally, we've upgraded Twilio so that it works properly from free accounts.

The PythonAnywhere newsletter, March 2016

Well, it's been nine months since our last newsletter and we've got a lot to tell you... Let's get started.

Cool new stuff part 1: Jupyter/IPython notebooks

Since the end of last year, all paid PythonAnywhere accounts have supported Jupyter/IPython notebooks. If you go to the "Files" tab, you can run existing notebooks, or create new ones. If you do anything involving data analysis, or exploratory interactive coding, they're a must-see.

We're still working out how to provide some kind of access for free users (without breaking the bank with our own server costs) so stay tuned...

Cool new stuff part 2: Education

Do you teach programming to a class of students? Do you have a coach who's helping you learn to code? Or do you just have a bunch of PythonAnywhere accounts and would like to access them all from one login?

With our new education feature, when you're logged into PythonAnywhere you can go to the "Account" tab and then to the "Teacher" section, and enter the username of another account. The person who's logged in to that other account can then "switch modes" so that they can use the site as if they are you. They can see your files, look at your consoles, and so on.

So -- if you're a teacher, next time you're running a class, ask your students to nominate you as their teacher, and you'll be able to help them without having to shoulder-surf. Super-useful for remote classes. (If you want us to bulk-create a bunch of accounts for your students beforehand, just get in touch on

If you're a student, just nominate your coach as your teacher, and they can help you with your coding questions quickly and easily.

And if you have a bunch of PythonAnywhere accounts that you want to access while logged in as a "superuser" account, just log in to each of the other accounts in turn and nominate your main account as the teacher. If you're a web developer using PythonAnywhere to host your customers' sites -- in separate accounts to make billing easier -- then you never need to wonder what the login details for each of the customers are.

There's more information here.

More cool new stuff! Part 3, custom consoles

Do you often need to start a console running a particular script? Maybe there's a metrics script you run once a day to find out how much money your wildly-successful website has made over the last 24 hours :-) Or maybe you just want to download some data to update your site.

On the "Consoles" tab, you can add a custom console to do whatever you want. Click on the little "+" icon next to "Custom", and you can enter a name (for you to recognise it by) and a bash command, or a path to a script. Click the checkmark, and you'll have a new custom script on your "Consoles" tab. From now on, every time you want to launch your script, it's just a click away.

Give it a go -- you'll be surprised how many helpful scripts you wind up adding.

More about custom consoles in this blog post.

Yet more cool new stuff! Part 4, web app hit counting

How busy is your website? If you have a free account, you can now go to the "Web" tab and see how many hits you've had in the last hour, day or month -- and comparable numbers for last month. And if you're a paying customer, you get pretty live charts you can zoom into and analyse in depth :-)

Pretty pictures here.

Even more cool new stuff! Part 5, a better editor

We've made our in-browser editor (the one you get if you click on a .py file in the "Files" tab) much better. Many thanks for everyone for the suggestions! There are two really noticeable changes:

  • The console that shows the results of your code when you click the "Save and run" button is no longer in a popup tab -- it's right there in the editor. No more problems with popup blockers, or having to click back and forth between tabs.
  • "Save as" -- it's kind of silly that our editor didn't have this. Now it does :-)

Stuff that isn't really very cool but you probably need to know!

  • Since day one, we've provided a MySQL database for everyone. The hostname we suggested for accessing it was simply mysql.server. (We have stuff in place so that address can point to different places for different people.) That wasn't working too well, unfortunately -- basically, the stuff to make the same address go to different servers for different people made it kind of slow -- so we've changed the address. If you go to the "Databases" tab and look at the top, in the "Connecting" section, you'll see a "Database host address", which is the one you should use now. That address isn't accessible from outside PythonAnywhere (for security reasons) but it will work inside.

    We are removing support for the mysql.server address in the very near future (probably about a month), so update your config accordingly.

  • Website CNAMEs. If you have a paid account and are using a custom domain, we used to tell you to point a CNAME at This really confused lots of people, because you can also have a website at, and that might be showing a completely different site to the one on your custom domain. We've revamped that, and now you can specify a different numeric CNAME value that doesn't host a site at all. We recommend you change over -- though, again, we'll continue to support the old-style CNAME for the time being.

From the forums and our blog

New modules

Although you can install Python packages on PythonAnywhere yourself, we like to make sure that we have plenty of batteries included. Here's what we've added since the last newsletter:

Python 2.7

plotly (1.9.3)
Upgraded tweepy to 3.5.0 (so that it works with Twitter's latest API)

Python 3.3 and 3.4

We added around 150 packages so that Python 3 packages match (as much as possible) the packages that are available for Python 2.

Here are some highlights, but you can visit the complete list for more details.

GitPython (1.0.1)
google-api-python-client (1.4.1)
pycurl (
pyflakes (0.9.2)
pyspotify (2.0.0)
tweepy (3.3.0)
xlrd (0.9.3)
xlwt (1.0.0)

New whitelisted sites

If you're a free PythonAnywhere user, you may have hit problems when writing code that tries to access sites elsewhere on the Internet. We have to restrict you to sites on a whitelist -- ones with an official public API -- to stop hackers from using us as a one-stop-shop to hide their identities when doing nefarious things. But we keep adding stuff to the whitelist; since our last newsletter, we've added over 100 new sites, but here are some that you may recognise:

And that's it!

Thanks for reading, and tune in next month for another exciting newsletter from PythonAnywhere.

Webapps and scheduled task expiries

tl;dr: for free accounts, web apps and scheduled tasks will stop running after a while if you don't log in. We'll email you a warning before this happens. Here's why:

Loads of people create free Python websites on PythonAnywhere and this is a really cool thing. Some of these websites are active ones where people are hosting their personal stuff, doing academic things, etc., and they want to keep them running. This is awesome! We want people to do that and we're happy to host this stuff for free.

For other use cases, some people may setup a webapp to try out a new web framework. Their owners may not intend to keep them running forever. That's fine too! We're glad to help people learn.

The problem for us is that we can't tell which is which.

Search engines such as Google and Baidu, and other web crawlers continuously index and hit all of the free websites, so they all look active, even the ones that nobody is using. We also didn't have any mechanism to tell which scheduled tasks were still important to their owners.

We don't want to reduce the service that we offer for free. We think it's an important way to give back to the community (and of course lots of free users start paying us after a while -- the record is a free user who started paying us after three years! -- so we have an incentive there too ;-)

On the other hand, PythonAnywhere is also very focused on offering a long term, sustainable service. In order to be a long term solution for you, we need a way to avoid accumulating dead code that will just grow and grow with no way of reducing it.

So, we've added a way for people to say "I'm still interested in keeping this web app/task running". Every three months (for web apps) or four weeks (for scheduled tasks) we'll email you to check. If you want to keep it up and running, there's a link in the email to click that will make sure it's all good for another three months or four weeks as appropriate. If you don't, you can just ignore the email.

If you miss the expiry email, all is not lost -- we won't delete anything. All your files, webapp setup, tasks and task logs will still be kept, but they just won't be actively running. You just need to login and click a button to re-enable them, and they will be extended by 3 months/4 weeks again.

We hope this works out OK, and helps us avoid running stuff that nobody wants anymore, which adds unnecessary congestion to the servers and ultimately increases the costs we have to charge our paying customers. Hopefully, it is a good balance between the two goals of being long term sustainable and making sure that we can continue to host stuff that people actually want for free.

Reach out to us if you have any thoughts!

Page 3 of 16.

« More recent postsOlder posts »

PythonAnywhere is a Python development and hosting environment that displays in your web browser and runs on our servers. They're already set up with everything you need. It's easy to use, fast, and powerful. There's even a useful free plan.

You can sign up here.