December 2009
November 2009
October 2009
September 2009
June 2009
April 2009
March 2009
February 2009
January 2009
December 2008
November 2008
October 2008
July 2008
June 2008
October 2007
September 2007
The most fundamental of abilities in shell scripts is moving about the file system.
import os os.chdir('/') contents = os.listdir(os.getcwd())
To change directories, we use os.chdir with an argument of our destination. To get a listing of the contents of a directory, os.listdir is the command to use. It takes one argument, which is the directory that holds the contents. If we want to know our current location on the filesystem, then os.getcwd will tell us the path.
Instead of moving around, you may want to do the same thing on the files and folders of a tree of directories, a.k.a. a recursive operation. In this next scenario, I have a hypothetical module called mp32vorbis that has a convert function, which converts a specified mp3 file into an ogg vorbis file.
import os import mp32vorbis for root, dirs, files in os.walk(os.getcwd()): for dir in dirs: print "Processing", os.path.join(root, dir) for file in files: if file.endswith('.mp3'): print "Converting", file mp32vorbis.convert(file)
As you can see, recursive operations are quick and easy with os.walk. It is a generator that yields each directory, root, plus a collection of directories and files within it. You can process each separate directory and file by looping through them. You may have noticed os.path.join. This is a simple function that connects its arguments with the directory separator of the host OS, which is backslashes for Windows and forward slashes for everything else.
At times, you will have to get and set environment variables to get the desired effect in your scripts. The os module offers this function through a dictionary like object called environ.
import os homedir = os.environ['HOME'] if not '/opt/mysuite/bin' in os.environ['PATH']: os.environ['PATH'] += ':/opt/mysuite/bin' os.system('mysuiteapp') # Executable in /opt/mysuite/bin
So you are running programs from python now. Perhaps you want to check that a file is readable and executable before trusting it to run? The os module comes to the rescue once again!
import os filename = 'bin/someprogram' if not os.path.exists(filename): print filename, 'does not exist!' raise SystemExit, 2 if not os.access(filename, os.R_OK): print filename, 'is not readable!' raise SystemExit, 3 if not os.access(filename, os.X_OK): print filename, 'is not executable!' raise SystemExit, 4
We would like to know that the file exists. This is determined with os.path.exists. Is the file readable and executable? We can find out with os.access and a couple of constants from the os module, os.R_OK and os.X_OK. We could also test if a file is writeable with os.access. We just use the os.W_OK constant. Simple, yes?
Would you like to know the times of creation, modification, and access? What about file size?
import datetime import os filename = 'somedir/somefile' ctime = datetime.datetime.fromtimestamp(os.path.getctime(filename)) mtime = datetime.datetime.fromtimestamp(os.path.getmtime(filename)) atime = datetime.datetime.fromtimestamp(os.path.getatime(filename)) sizeinbytes = os.path.getsize(filename)
It is pretty straight forward. You might be wondering about why I am using datetime.datetime.fromtimestamp here. The os.path.getXtime functions all spit out POSIX timestamps. In python, it is more useful to have these be python datetimes. The datetime.datetime.fromtimestamp function produces a datetime object from a given timestamp.
Like shell scripts, python may not be able to do everything you want by itself. You may need to execute an external program to get the job done.
NOTE: This is the old way to call external programs and still valid for python versions 2.3 and earlier. However, if you are using 2.4 or later, then use subprocess. The documentation for subprocess is very flushed out so I will not be expanding on it here.
Python's os module offers loads of ways to accomplish this. I will cover only the ones you are to use when replacing shell scripts.
import os return_status = os.system('ping -c 5 localhost')
The os.system function is the least useful. I will execute a command as specified and return the return status of the program. This is especially useless on operating systems with inconsistent return statuses, i.g. Windows. Any output from the program will be sent to the standard locations, stdout and stderr.
import os output = os.popen('ping -c 5 localhost') print output.read() # Streams are file-like
Perhaps you might want to capture the program's output for later. The os.popen function returns a stream of the output from the program. These streams are handled just like files in python. Use the read and readline methods to access the output. With popen, the function returns immediately, so you can run multiple external programs at once.
import os stdin, stdout = os.popen2('sed s/p/q/g') stdin.writelines('Replace the ps with qs please') stdin.close() print stdout.readline() # prints Reqlace qs with qs qlease
What if you want to give the program a little input? The os.popen2 function lets you do just that. It returns a file stream to both the stdin and stdout of the program. Just write your input, close the stdin stream, and read the output. There are more popen functions. The os.popen3 returns file streams to stdin, stdout, and stderr. os.popen4 returns two file streams, the stdin and the merged stdout/stderr.
You might need to make folders and link files from time to time. The os module is used for both of these tasks.
import os os.mkdir('newdir') # like mkdir os.makedirs('notexistent/bogus/newdir') # like mkdir -p
os.mkdir and os.makedirs offer little in the way of surprises. os.mkdir works like mkdir and os.makedirs works like mkdir -p, creating any intermediate directories it needs to create the specified directory.
import os os.link('file', 'newhardlink') # think ln os.symlink('fileordir', 'newsymlink') # think ln -s
os.link creates hard links to files just like ln. os.symlink creates soft links in the way that ln -s does. I love how python works in such a predictable fashion.
