Running Python on your own computer

Today we will combine what we learned in lesson 1 about our own computers systems with what we have been learning in Codecademy about Python, and look at the different ways you can run Python programs on your own computer. There are essentially four ways to do this:

  • Run python at the command line, as another shell. (Remember what a shell is?)
  • Write a program into a file and then run Python with that filename as an argument (e.g. python myprogram.py)
  • Run Python in a notebook such as this one
  • Run Python in a graphical program for developers, known as an IDE

Go ahead and open a Powershell / Terminal window, and run the python command. You will see something like this:

MacBook-Pro-2:TT2016 tla$ python
Python 3.4.4 (default, Jan  5 2016, 13:43:49) 
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Observe that the prompt has changed - those three arrows are now the signal that the program is ready to listen to you.

Now we can try something simple:


In [24]:
print('Hello, world!')


Hello, world!

You can also write a program into a file and then execute it like so:

MacBook-Pro-2:~ tla$ cat Documents/test.py 
print("Hello, this is a test and it works!")
MacBook-Pro-2:~ tla$ python Documents/test.py 
Hello, this is a test and it works!

As we will learn later, it is possible to give more arguments at the command line, which your Python program can use to do other things. Usually if you are given a Python program by someone else, this is how you will run it.

You can also run Python in a notebook like this one.

PS C:\Users\Tara L Andrews> jupyter notebook
[I 08:33:23.342 NotebookApp] Serving notebooks from local directory: C:\Users\Tara L Andrews
[I 08:33:23.342 NotebookApp] 0 active kernels
[I 08:33:23.342 NotebookApp] The Jupyter Notebook is running at: http://localhost:8888/
[I 08:33:23.342 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).

Your command prompt won't come back, but instead a web browser window will open and you will be able to make a new notebook document much like this one.


In [25]:
year = 2015
print("Let's party like it's", year)


Let's party like it's 2015

Just like the Python interactive shell (and unlike running a Python program from a file), the IPython notebook remembers everything you define until you restart it. This is why we call them "interactive" - you can define things, look at them, and then do things with them without having to start over every time.


In [27]:
year += 1
print("Now we are partying like it's", year)


Now we are partying like it's 2017

The fourth way to run Python, which is fairly complex-looking at first but becomes much more useful the more you program, is through an IDE. When you installed Anaconda you got an IDE called "Spyder" along with it. Go ahead and start it up and have a look around. Open the Python file you ran at the command line a while ago, and run it in Spyder.

Spyder is also a non-interactive version of Python - when you run a program, it starts over fresh from the beginning and forgets everything that you ran before. However, like all IDEs Spyder has a debugger, which means that you can stop the program in the middle and have a closer look at what it is doing!

Getting around your filesystem from Python

You have seen that Spyder asks you questions about your "working directory", and that it starts you with a temporary file in some crazy location you don't want to remember. This is a good moment to talk about how Python works with the filesystem that we learned about in week 1.

Python has a bunch of tools for interacting with your operating system, and they are all in the os module. We can get access to it with the following line of code:


In [28]:
import os

We can list the contents of any directory by using the os.listdir() method. Without any arguments, it gives us the contents of the directory we are standing in.


In [29]:
os.listdir()


Out[29]:
['.adobe',
 '.astropy',
 '.bash_history',
 '.bash_sessions',
 '.pip',
 '.profile',
 '.Xauthority',
 '644_col.txt',
 'a',
 'anaconda',
 'Applications',
 'Desktop',
 'Docear',
 'DocLocal',
 'Documents',
 'DocVC',
 'Downloads',
 'Dropbox',
 'Library',
 'Movies',
 'Music',
 'www']

We can also list the contents of any other directory. For example, the Downloads folder on my Mac is in the folder with my short name (tla), which is in a folder called Users, which is right on the Macintosh HD. So I say

/Users/tla/Downloads

to get at it. That is: Starting at the root (/), look in Users; starting at Users (/Users/), look in tla; starting at tla (/Users/tla/), look in Downloads.

If you are on Windows you will probably want something like /Users/Tara Andrews/Downloads instead.

Let's print out each of the filenames we find in that directory.


In [30]:
for f in os.listdir("/Users/tla/Downloads"):
    print(f)


.DS_Store
About Downloads.lpdf
AM2004.rtf
AM2004.txt
Anaconda3-2.5.0-MacOSX-x86_64.pkg
ANAST. SIN. Homilia dicta in sextum psalmum. Rec. II.xml
Head_First_Java_Second_Edition.epub
hearingsdigitalhumanities1.doc
world_innodb.sql

Python (or any program running on your computer for that matter) always runs from some specific place in this filesystem - that is, some specific directory on your drive. To see where you are running now, you can ask for the current working directory, like so. Try this command in Python at the command line, in IPython, and in Spyder, and see what you get.


In [32]:
os.getcwd()


Out[32]:
'/Users/tla'

This will look a little different on Mac vs. Windows, because they use different notations (called the path) for their directory structure.

C:\Users\Tara L Andrews\Documents\IPython Notebooks

vs.

/Users/tla/Documents/2014 FS

The two important lessons to take from this are:

  • If you are not sure where you are, then os.getcwd() will tell you.
  • If you value your sanity, don't use / or \ when you name your folders and files.

Once you know where you are on the filesystem, you can change directory. This is accomplished with the os.chdir() method. For example:


In [33]:
os.chdir("/Users/tla")   # go to the directory tla in the directory Users at the base of the drive
os.chdir("..")           # go one directory down
print(os.getcwd())       # see where we are

os.chdir("./tla/Downloads")  # go to the directory Downloads in the directory tla that is here where we are
print(os.getcwd())           # see where we are now


/Users
/Users/tla/Downloads

You will remember that there are a few special names when you look at files and directories:

.  - the directory I'm standing in
.. - the directory that holds the directory I'm standing in
/  - (all by itself) the base ("root") directory

IF YOU ARE ON WINDOWS: The / is a little more complicated than that if you are on Windows. As you will have noticed, you often see \ instead of /, but Python (like Powershell) lets you call it / anyway. Moreover, it is the base directory of the drive you are currently looking at (e.g. C:, D:, or whatever.)

IF YOU ARE ON MAC OR LINUX: Unix machines (including Macs) don't deal with drives in the same way, so / just means the root of your OS filesystem.

So by saying

os.chdir("..")

we have moved down a directory. We could keep doing this all the way to the bottom, if we felt like it. But generally it is a good idea to stay in your home directory if you have the choice.

Here is how Python knows what your home directory is:


In [34]:
print(os.getenv("HOME", "I don't have a HOME variable, so I must be on Windows"))
print(os.getenv("USERPROFILE", "I don't have a USERPROFILE variable, so I must be on Mac or Linux" ))


/Users/tla
I don't have a USERPROFILE variable, so I must be on Mac or Linux

Once you know which variable contains your home directory, you can save it into a variable and use it.


In [35]:
my_home = os.getenv("HOME")
for f in os.listdir( my_home ):
    print(f)


.adobe
.astropy
.bash_history
.bash_sessions
.pip
.profile
.Xauthority
anaconda
Applications
beer.pl
bifurc.png
caesar.dot
caesar.svg
caesar.xml
caesar.zip
cloud_reinstallation.txt
CloudStation
collatex
demo
Desktop
Docear
DocLocal
Documents
DocVC
Downloads
Dropbox
Library
Movies
Music
Projects
Public
pubs.bib
restored.txt
scratch
smbat_410.txt
V917
www

Now, if I want to, I can look to see what we have in my Projects folder - this is where I usually keep the code I've worked on. I can do this by joining the directory name ('Projects') to my home directory (which I've saved in my_home.)


In [ ]:
doc_path = os.path.join( my_home, "Projects" )
print( "The join operation has given me the path", doc_path )
os.listdir( doc_path )

Using the os.path.join command is a very good idea when you don't know what kind of computer might be running your script - it means that you are letting Python deal with the question of whether the path separator is / or \ or : or % or whatever. But you don't have to use the os.path.join command if you know that / will work; you can also just type the path directly.


In [ ]:
os.listdir( "/Users/tla/Dropbox/book" )   # Look at the 'book' folder in the Dropbox folder in my home directory

So to sum up, here are some equivalences between the command line and Python:

cd DIRECTORY ==> os.chdir("DIRECTORY")
ls DIRECTORY ==> os.listdir("DIRECTORY")
pwd          ==> os.getcwd()
echo $VAR    ==> os.getenv("VAR")

Reading files

Now that we know how to navigate around our directory, we might also want to look inside some files! Here's how we do that.


In [36]:
fh = open(my_home + "/Dropbox/beef_stew.txt")   # Open the file
contents = fh.read()                        # Read its contents
fh.close()                                  # Close the file
print(contents)                             # Do something with the contents


500 grams of beef
heat a mixture of about 30 grams of butter and three tablespoons of olive oil
put in the meat, fry brownish on all sides
keep turning
add plenty of pepper, salt, coriander, rosemary, nutmeg
add a glass of white wine
add a cube of dried beef broth 
add a glass of water
(the meat should almost be under the moisture, but not completely)
add two bay leaves
add just short of a tablespoon of normal mustard
same for brown sugar
Turn the heat down as far as possible, ideally 99C but err on the low side
now sit back for at least three hours
enjoy

There are three steps to dealing with files from Python:

  1. Open it
  2. Read (or write) whatever you need
  3. Close it

When you open a file, you make something called a filehandle. The filehandle, well, handles the file - does the reading, writing, closing, etc. that you need to be done.

When you read a file, you have two choices: read in the entire thing, or read it line-by-line. If the file is small, or if you don't want to process it line-by-line, then you will read it all in one go. If it makes sense to process one line at a time (and especially if it is a huge file), then by all means do so. So, for example, we could add line numbers to what is in this file.


In [37]:
os.chdir(my_home)
fh = open( "Dropbox/beef_stew.txt" )
counter = 1
for line in fh:
    print("%d: %s" % ( counter, line ))
    counter += 1
fh.close()


1: 500 grams of beef

2: heat a mixture of about 30 grams of butter and three tablespoons of olive oil

3: put in the meat, fry brownish on all sides

4: keep turning

5: add plenty of pepper, salt, coriander, rosemary, nutmeg

6: add a glass of white wine

7: add a cube of dried beef broth 

8: add a glass of water

9: (the meat should almost be under the moisture, but not completely)

10: add two bay leaves

11: add just short of a tablespoon of normal mustard

12: same for brown sugar

13: Turn the heat down as far as possible, ideally 99C but err on the low side

14: now sit back for at least three hours

15: enjoy

Huh, great, but why did that double-space all of a sudden?

Here's what happened: every line in the file ends with a line break where I pressed Return. The print function adds a line break after everything it prints, by default. Since the lines in the file already have one, if we are not careful we will also be double-spacing the printout! In order to avoid that, we end the print statement with this parameter

end=""

which says "Instead of the newline you would normally print at the end, print nothing instead."


In [38]:
fh = open( "Dropbox/beef_stew.txt" )
counter = 1
for line in fh:
    print("%d: %s" % ( counter, line ), end="")
    counter += 1
fh.close()


1: 500 grams of beef
2: heat a mixture of about 30 grams of butter and three tablespoons of olive oil
3: put in the meat, fry brownish on all sides
4: keep turning
5: add plenty of pepper, salt, coriander, rosemary, nutmeg
6: add a glass of white wine
7: add a cube of dried beef broth 
8: add a glass of water
9: (the meat should almost be under the moisture, but not completely)
10: add two bay leaves
11: add just short of a tablespoon of normal mustard
12: same for brown sugar
13: Turn the heat down as far as possible, ideally 99C but err on the low side
14: now sit back for at least three hours
15: enjoy

Writing to files

When we open a filehandle on a particular file, that filehandle can either be reading from the file or writing to it (but not both, at least not until we understand the mechanics and the dangers of doing that.)

When we write to a file that already exists, there are two options: either we will replace whatever was there before, or we will add to it. Let's try it, first to a new file and then adding something to that file.

When we use the open() function, it takes two parameters: the filename and a letter that indicates whether we want to read or write or what. If we don't give any letter, it assumes we meant 'r' for 'read'. The options are:

  • r - open the file to reading
  • w - empty the file and open it to writing
  • a - open the file for writing (appending) to the end; do NOT empty it.

We can see this in action, by opening the old recipe for reading and a new recipe for writing. Where we use .read() on the old filehandle, we will use .write() on the new filehandle.

The write function is a lot like print, only it does NOT assume that you want a line break at the end. In this case that is pretty convenient, since we don't!


In [39]:
old_recipe = open( "Dropbox/beef_stew.txt" )
new_recipe = open( "Dropbox/numbered_beef_stew.txt", "w" )
counter = 1
for line in old_recipe:
    new_recipe.write( "%d: %s" % ( counter, line ) )
    counter += 1  # this is the same as counter = counter + 1
old_recipe.close()
new_recipe.close()

So let's look at the new recipe! We open it for reading this time, instead of writing. And instead of reading it line by line, we will read it all in one go, so that we don't have to worry about what print does with line endings.


In [ ]:
new_recipe = open( "Dropbox/numbered_beef_stew.txt" )
contents = new_recipe.read()
new_recipe.close()

print(contents)

Let's say we forgot a step at the end, and want to add it.

When we write a new line to the file, since we are using .write() and not print(), we have to make sure to add the carriage return at the end of the line. In Python this can usually be done with the term "\n", no matter which sort of computer you are on. (This fact can confuse nerds used to the old ways of things, but is convenient for you!)

Finally, although it is always important to close the files we open, it is especially important if we are writing to the file. If we forget to close a file we're writing to, then it's possible that not everything will get written!


In [40]:
new_recipe = open( "Dropbox/numbered_beef_stew.txt", "a" )
new_recipe.write( "18: give the leftovers to the cat\n" )
new_recipe.close()

And let's see if that worked. This time, instead of using .read() to put the file into a single variable, we will use .readlines() to put the file line by line into an array. This is useful if you want to read the file all in one go, but are going to want to do something with its contents line by line.


In [41]:
new_recipe = open( "Dropbox/numbered_beef_stew.txt" )
contents = new_recipe.readlines()
new_recipe.close()

for line in contents:
    print("-", line, end='')


- 1: 500 grams of beef
- 2: heat a mixture of about 30 grams of butter and three tablespoons of olive oil
- 3: put in the meat, fry brownish on all sides
- 4: keep turning
- 5: add plenty of pepper, salt, coriander, rosemary, nutmeg
- 6: add a glass of white wine
- 7: add a cube of dried beef broth 
- 8: add a glass of water
- 9: (the meat should almost be under the moisture, but not completely)
- 10: add two bay leaves
- 11: add just short of a tablespoon of normal mustard
- 12: same for brown sugar
- 13: Turn the heat down as far as possible, ideally 99C but err on the low side
- 14: now sit back for at least three hours
- 15: enjoy
- 18: give the leftovers to the cat

You can open and close a file as often as you need to in the same program, as long as you always close it before reopening it somewhere else!

Once you know your way around the files and directories on your system, a lot of things start to make a lot more sense...

  • Spyder and its default temporary script
  • Saving and running a Python program
  • Making a spreadsheet file out of some geographic data you have, and saving it somewhere for import to Google Maps, which we will do later this semester!