One thing a computer can do that most humans can’t is be sealed up in a cardboard box and sit in a warehouse.
Jack Handey
In your everyday use of a computer, you do such things as list the contents of a folder or directory, create and remove files, and other housekeeping that’s necessary if not particularly exciting. You can also carry out these tasks, and more, within your own Python programs. Will this power drive you mad or cure your insomnia? We’ll see.
Python provides many system functions through a module named os
(for
“operating system”), which we’ll import for all the programs in this
chapter.
Python, like many other languages,
patterned its file operations after Unix.
Some functions, such as chown()
and chmod()
,
have the same names,
but there are a few new ones.
“File Input/Output” introduced you to the open()
function and explains how you can use it to open a file or create one if it doesn’t already exist.
Let’s create a text file called oops.txt:
>>>
fout
=
open
(
'oops.txt'
,
'wt'
)
>>>
(
'Oops, I created a file.'
,
file
=
fout
)
>>>
fout
.
close
()
With that done, let’s perform some tests with it.
To verify whether the file or directory is really there or you just imagined it, you can provide exists()
, with a relative or absolute pathname, as demonstrated here:
>>>
import
os
>>>
os
.
path
.
exists
(
'oops.txt'
)
True
>>>
os
.
path
.
exists
(
'./oops.txt'
)
True
>>>
os
.
path
.
exists
(
'waffles'
)
False
>>>
os
.
path
.
exists
(
'.'
)
True
>>>
os
.
path
.
exists
(
'..'
)
True
The functions in this section check whether a name refers to a file, directory, or symbolic link (see the examples that follow for a discussion of links).
The first function we’ll look at, isfile
, asks a simple question: is it a plain old law-abiding file?
>>>
name
=
'oops.txt'
>>>
os
.
path
.
isfile
(
name
)
True
Here’s how you determine a directory:
>>>
os
.
path
.
isdir
(
name
)
False
A single dot (.
) is shorthand for the current directory,
and two dots (..
) stands for the parent directory.
These always
exist, so a statement such as the following will always report True
:
>>>
os
.
path
.
isdir
(
'.'
)
True
The os
module contains many functions dealing with pathnames
(fully qualified filenames, starting with /
and including all parents).
One such function, isabs()
, determines whether its argument
is an absolute pathname. The argument doesn’t need to be the name of
a real file:
>>>
os
.
path
.
isabs
(
name
)
False
>>>
os
.
path
.
isabs
(
'/big/fake/name'
)
True
>>>
os
.
path
.
isabs
(
'big/fake/name/without/a/leading/slash'
)
False
In Unix, a file exists in one place,
but it can have multiple names, called links.
In low-level hard links,
it’s not easy to find all the names for a given file.
A symbolic link is an alternative method
that stores the new name as its own file,
making it possible for you to get both the original and new names at once.
The link()
call creates a hard link,
and symlink()
makes a symbolic link.
The islink()
function checks whether the file is a symbolic link.
Here’s how to make a hard link to the existing file oops.txt from the new file yikes.txt:
>>>
os
.
link
(
'oops.txt'
,
'yikes.txt'
)
>>>
os
.
path
.
isfile
(
'yikes.txt'
)
True
To create a symbolic link to the existing file oops.txt from the new file jeepers.txt, use the following:
>>>
os
.
path
.
islink
(
'yikes.txt'
)
False
>>>
os
.
symlink
(
'oops.txt'
,
'jeepers.txt'
)
>>>
os
.
path
.
islink
(
'jeepers.txt'
)
True
On a Unix system, chmod()
changes file permissions.There are read,
write, and execute permissions for the user (that’s usually you, if you
created the file), the main group that the user is in, and the rest of
the world. The command takes an intensely compressed octal (base 8)
value that combines user, group, and other permissions. For instance,
to make oops.txt only readable by its owner, type the following:
>>>
os
.
chmod
(
'oops.txt'
,
0
o400
)
If you don’t want to deal with cryptic octal values and would rather
deal with (slightly) obscure cryptic symbols, you can import some
constants from the stat
module and use a statement such as the following:
>>>
import
stat
>>>
os
.
chmod
(
'oops.txt'
,
stat
.
S_IRUSR
)
In one of the earlier sections, we made a symbolic
link to oops.txt from the new file jeepers.txt.
In circumstances such as this, you can get the name of oops.txt from jeepers.txt by using the realpath()
function, as shown here:
>>>
os
.
path
.
realpath
(
'jeepers.txt'
)
'/usr/gaberlunzie/oops.txt'
In most operating systems,
files exist in a hierarchy of directories (more often called folders these days).
The container of all of these files and directories
is a file system (sometimes called a volume).
The standard os
module deals with operating specifics
such as these and provides the following functions with which you can manipulate them.
Okay, take two; let’s make poems
again, with some contents:
>>>
os
.
mkdir
(
'poems'
)
Now, get a list of its contents (none so far):
>>>
os
.
listdir
(
'poems'
)
[]
>>>
os
.
mkdir
(
'poems/mcintyre'
)
>>>
os
.
listdir
(
'poems'
)
['mcintyre']
Create a file in this subdirectory (don’t type all these lines unless you really feel poetic; just make sure you begin and end with matching quotes, either single or tripled):
>>>
fout
=
open
(
'poems/mcintyre/the_good_man'
,
'wt'
)
>>>
fout
.
write
(
'''Cheerful and happy was his mood,
...
He to the poor was kind and good,
...
And he oft' times did find them food,
...
Also supplies of coal and wood,
...
He never spake a word was rude,
...
And cheer'd those did o'er sorrows brood,
...
He passed away not understood,
...
Because no poet in his lays
...
Had penned a sonnet in his praise,
...
'Tis sad, but such is world's ways.
...
'''
)
344
>>>
fout
.
close
()
Finally, let’s see what we have. It had better be there:
>>>
os
.
listdir
(
'poems/mcintyre'
)
['the_good_man']
The glob()
function matches file or directory names
by using Unix shell rules
rather than the more complete regular expression syntax. Here are those rules:
*
matches everything (re
would expect .*
)
?
matches a single character
[abc]
matches character a
, b
, or c
[!abc]
matches any character except a
, b
, or c
Try getting all files or directories that begin with m
:
>>>
import
glob
>>>
glob
.
glob
(
'm*'
)
['mcintyre']
How about any two-letter files or directories?
>>>
glob
.
glob
(
'??'
)
[]
I’m thinking of an eight-letter word that begins with m
and ends with e
:
>>>
glob
.
glob
(
'm??????e'
)
['mcintyre']
What about anything that begins with a k
, l
, or m
, and ends with e
?
>>>
glob
.
glob
(
'[klm]*e'
)
['mcintyre']
When you run an individual program, your operating system creates a single process. It uses system resources (CPU, memory, disk space) and data structures in the operating system’s kernel (file and network connections, usage statistics, and so on). A process is isolated from other processes—it can’t see what other processes are doing or interfere with them.
The operating system keeps track of all the running processes, giving each a little time to run and then switching to another, with the twin goals of spreading the work around fairly and being responsive to the user. You can see the state of your processes with graphical interfaces such as the Mac’s Activity Monitor (OS X), or Task Manager on Windows-based computers.
You can also access process data from your own programs.
The standard library’s os
module provides a common way of
accessing some system information.
For instance, the following functions get the process ID
and the current working directory
of the running Python interpreter:
>>>
import
os
>>>
os
.
getpid
()
76051
>>>
os
.
getcwd
()
'/Users/williamlubanovic'
And these get my user ID and group ID:
>>>
os
.
getuid
()
501
>>>
os
.
getgid
()
20
All of the programs that you’ve seen here so far have been individual processes.
You can start and stop other existing programs from Python by using the
standard library’s subprocess
module.
If you just want to run another program in a shell
and grab whatever output it created
(both standard output and standard error output),
use the getoutput()
function.
Here, we’ll get the output of the Unix date
program:
>>>
import
subprocess
>>>
ret
=
subprocess
.
getoutput
(
'date'
)
>>>
ret
'Sun Mar 30 22:54:37 CDT 2014'
You won’t get anything back until the process ends.
If you need to call something that might take a lot of time,
see the discussion on concurrency in “Concurrency”.
Because the argument to getoutput()
is a string representing a
complete shell command, you can include arguments, pipes,
<
and >
I/O redirection, and so on:
>>>
ret
=
subprocess
.
getoutput
(
'date -u'
)
>>>
ret
'Mon Mar 31 03:55:01 UTC 2014'
Piping that output string to the wc
command counts
one line, six “words,” and 29 characters:
>>>
ret
=
subprocess
.
getoutput
(
'date -u | wc'
)
>>>
ret
' 1 6 29'
A variant method called check_output()
takes a list of
the command and arguments.
By default it only returns standard output
as type bytes rather than a string
and does not use the shell:
>>>
ret
=
subprocess
.
check_output
([
'date'
,
'-u'
])
>>>
ret
b'Mon Mar 31 04:01:50 UTC 2014 '
To show the exit status of the other program,
getstatusoutput()
returns a tuple with the status code and output:
>>>
ret
=
subprocess
.
getstatusoutput
(
'date'
)
>>>
ret
(0, 'Sat Jan 18 21:36:23 CST 2014')
If you don’t want to capture the output
but might want to know its exit status, use call()
:
>>>
ret
=
subprocess
.
call
(
'date'
)
Sat Jan 18 21:33:11 CST 2014
>>>
ret
0
(In Unix-like systems, 0
is usually the exit status for success.)
That date and time was printed to output but not captured within our program.
So, we saved the return code as ret
.
You can run programs with arguments in two ways.
The first is to specify them in a single string.
Our sample command is date -u
,
which prints the current date and time in UTC (you’ll read more about UTC in a few pages):
>>>
ret
=
subprocess
.
call
(
'date -u'
,
shell
=
True
)
Tue Jan 21 04:40:04 UTC 2014
You need that shell=True
to recognize the command line date -u
,
splitting it into separate strings and possibly
expanding any wildcard characters such as *
(we didn’t use any in this example).
The second method makes a list of the arguments, so it doesn’t need to call the shell:
>>>
ret
=
subprocess
.
call
([
'date'
,
'-u'
])
Tue Jan 21 04:41:59 UTC 2014
You can run a Python function as a separate process
or even run multiple independent processes in a single program
with the multiprocessing
module.
Here’s a short example that does nothing useful;
save it as mp.py and then run it by typing python mp.py
:
import
multiprocessing
import
os
def
do_this
(
what
):
whoami
(
what
)
def
whoami
(
what
):
(
"Process
%s
says:
%s
"
%
(
os
.
getpid
(),
what
))
if
__name__
==
"__main__"
:
whoami
(
"I'm the main program"
)
for
n
in
range
(
4
):
p
=
multiprocessing
.
Process
(
target
=
do_this
,
args
=
(
"I'm function
%s
"
%
n
,))
p
.
start
()
When I run this, my output looks like this:
Process 6224 says: I'm the main program Process 6225 says: I'm function 0 Process 6226 says: I'm function 1 Process 6227 says: I'm function 2 Process 6228 says: I'm function 3
The Process()
function spawned a new process and ran the do_this()
function in it. Because we did this in a loop that had four passes,
we generated four new processes that executed do_this()
and then exited.
The multiprocessing
module has more bells and whistles than
a clown on a calliope.
It’s really intended for those times when you need to farm out some task to multiple processes
to save overall time; for example, downloading web pages for scraping,
resizing images,
and so on.
It includes ways to queue tasks,
enable intercommunication among processes,
and wait for all the processes to finish.
“Concurrency” delves into some of these details.
If you created one or more processes and want to terminate one for some reason
(perhaps it’s stuck in a loop, or maybe you’re bored, or you want to be an evil overlord),
use terminate()
.
In the example that follows,
our process would count to a million,
sleeping at each step for a second,
and printing an irritating message.
However, our main program runs out of patience in five seconds
and nukes it from orbit:
import
multiprocessing
import
time
import
os
def
whoami
(
name
):
(
"I'm
%s
, in process
%s
"
%
(
name
,
os
.
getpid
()))
def
loopy
(
name
):
whoami
(
name
)
start
=
1
stop
=
1000000
for
num
in
range
(
start
,
stop
):
(
"
Number
%s
of
%s
. Honk!"
%
(
num
,
stop
))
time
.
sleep
(
1
)
if
__name__
==
"__main__"
:
whoami
(
"main"
)
p
=
multiprocessing
.
Process
(
target
=
loopy
,
args
=
(
"loopy"
,))
p
.
start
()
time
.
sleep
(
5
)
p
.
terminate
()
When I run this program, I get the following:
I'm main, in process 97080 I'm loopy, in process 97081 Number 1 of 1000000. Honk! Number 2 of 1000000. Honk! Number 3 of 1000000. Honk! Number 4 of 1000000. Honk! Number 5 of 1000000. Honk!
Programmers devote a surprising amount of effort to dates and times. Let’s talk about some of the problems they encounter, and then get to some best practices and tricks to make the situation a little less messy.
Dates can be represented in many ways—too many ways, actually. Even in English with the Roman calendar, you’ll see many variants of a simple date:
July 29 1984
29 Jul 1984
29/7/1984
7/29/1984
Among other problems, date representations can be ambiguous.
In the previous examples, it’s easy to determine that 7 stands for the month
and 29 is the day of the month,
largely because months don’t go to 29.
But how about 1/6/2012
? Is that referring to January 6 or June 1?
The month name varies by language within the Roman calendar. Even the year and month can have a different definition in other cultures.
Leap years are another wrinkle. You probably know that every four years is a leap year (and the summer Olympics and the American presidential election). Did you also know that every 100 years is not a leap year, but that every 400 years is? Here’s code to test various years for leapiness:
>>>
import
calendar
>>>
calendar
.
isleap
(
1900
)
False
>>>
calendar
.
isleap
(
1996
)
True
>>>
calendar
.
isleap
(
1999
)
False
>>>
calendar
.
isleap
(
2000
)
True
>>>
calendar
.
isleap
(
2002
)
False
>>>
calendar
.
isleap
(
2004
)
True
Times have their own sources of grief, especially because of time zones and daylight savings time. If you look at a time zone map, the zones follow political and historic boundaries rather than every 15 degrees (360 degrees / 24) of longitude. And countries start and end daylight saving times on different days of the year. In fact, countries in the southern hemisphere advance their clocks when the northern hemisphere is winding them back, and vice versa. (If you think about it a bit, you will see why.)
Python’s standard library has many date and
time modules: datetime
, time
,
calendar
, dateutil
, and others.
There’s some overlap, and it’s a bit confusing.
Let’s begin by investigating the standard datetime
module.
It defines four main objects, each with many methods:
date
for years, months, and days
time
for hours, minutes, seconds, and fractions
datetime
for dates and times together
timedelta
for date and/or time intervals
You can make a date
object by specifying a year, month, and day.
Those values are then available as attributes:
>>>
from
datetime
import
date
>>>
halloween
=
date
(
2014
,
10
,
31
)
>>>
halloween
datetime.date(2014, 10, 31)
>>>
halloween
.
day
31
>>>
halloween
.
month
10
>>>
halloween
.
year
2014
You can print a date
with its isoformat()
method:
>>>
halloween
.
isoformat
()
'2014-10-31'
The iso
refers to ISO 8601,
an international standard for representing dates and times.
It goes from most general (year) to most specific (day).
It also sorts correctly: by year, then month, then day.
I usually pick this format for date representation in programs,
and for filenames that save data by date.
The next section describes the more complex
strptime()
and strftime()
methods for parsing and formatting dates.
This example uses the today()
method to generate today’s date:
>>>
from
datetime
import
date
>>>
now
=
date
.
today
()
>>>
now
datetime.date(2014, 2, 2)
This one makes use of a timedelta
object to add some time interval to a date
:
>>>
from
datetime
import
timedelta
>>>
one_day
=
timedelta
(
days
=
1
)
>>>
tomorrow
=
now
+
one_day
>>>
tomorrow
datetime.date(2014, 2, 3)
>>>
now
+
17
*
one_day
datetime.date(2014, 2, 19)
>>>
yesterday
=
now
-
one_day
>>>
yesterday
datetime.date(2014, 2, 1)
The range of date
is from
date.min
(year=1, month=1, day=1)
to date.max
(year=9999, month=12, day=31).
As a result, you can’t use it for historic or astronomical calculations.
The datetime
module’s time
object is used to represent a time of day:
>>>
from
datetime
import
time
>>>
noon
=
time
(
12
,
0
,
0
)
>>>
noon
datetime.time(12, 0)
>>>
noon
.
hour
12
>>>
noon
.
minute
0
>>>
noon
.
second
0
>>>
noon
.
microsecond
0
The arguments go from the largest time unit (hours) to the smallest (microseconds).
If you don’t provide all the arguments,
time
assumes all the rest are zero.
By the way,
just because you can store and retrieve microseconds
doesn’t mean you can retrieve time from your computer to the exact
microsecond. The accuracy of subsecond measurements depends on many
factors in the hardware and operating system.
The datetime
object includes both the date and time of day.
You can create one directly,
such as the one that follows, which is for January 2, 2014, at 3:04 A.M., plus 5 seconds
and 6 microseconds:
>>>
from
datetime
import
datetime
>>>
some_day
=
datetime
(
2014
,
1
,
2
,
3
,
4
,
5
,
6
)
>>>
some_day
datetime.datetime(2014, 1, 2, 3, 4, 5, 6)
The datetime
object also has an isoformat()
method:
>>>
some_day
.
isoformat
()
'2014-01-02T03:04:05.000006'
That middle T
separates the date and time parts.
datetime
has a now()
method with which you can get the current date and time:
>>>
from
datetime
import
datetime
>>>
now
=
datetime
.
now
()
>>>
now
datetime.datetime(2014, 2, 2, 23, 15, 34, 694988)
14
>>>
now
.
month
2
>>>
now
.
day
2
>>>
now
.
hour
23
>>>
now
.
minute
15
>>>
now
.
second
34
>>>
now
.
microsecond
694988
You can merge a date
object and a time
object
into a datetime
object by using combine()
:
>>>
from
datetime
import
datetime
,
time
,
date
>>>
noon
=
time
(
12
)
>>>
this_day
=
date
.
today
()
>>>
noon_today
=
datetime
.
combine
(
this_day
,
noon
)
>>>
noon_today
datetime.datetime(2014, 2, 2, 12, 0)
You can yank the date
and time
from a datetime
by using the date()
and time()
methods:
>>>
noon_today
.
date
()
datetime.date(2014, 2, 2)
>>>
noon_today
.
time
()
datetime.time(12, 0)
It is confusing that Python has a datetime
module with a time
object,
and a separate time
module.
Furthermore, the time
module has a function called—wait for it—time()
.
One way to represent an absolute time is to count the number of seconds since some starting point. Unix time uses the number of seconds since midnight on January 1, 1970.1 This value is often called the epoch, and it is often the simplest way to exchange dates and times among systems.
The time
module’s time()
function returns the current time as an epoch value:
>>>
import
time
>>>
now
=
time
.
time
()
>>>
now
1391488263.664645
If you do the math, you’ll see that it has been over one billion seconds since New Year’s, 1970. Where did the time go?
You can convert an epoch value to a string by using ctime()
:
>>>
time
.
ctime
(
now
)
'Mon Feb 3 22:31:03 2014'
In the next section, you’ll see how to produce more attractive formats for dates and times.
Epoch values are a useful least-common denominator for date and time exchange
with different systems, such as JavaScript.
Sometimes, though, you need actual days, hours, and so forth,
which time
provides as struct_time
objects.
localtime()
provides the time in your system’s time zone,
and gmtime()
provides it in UTC:
>>>
time
.
localtime
(
now
)
time.struct_time(tm_year=2014, tm_mon=2, tm_mday=3, tm_hour=22, tm_min=31,
tm_sec=3, tm_wday=0, tm_yday=34, tm_isdst=0)
>>>
time
.
gmtime
(
now
)
time.struct_time(tm_year=2014, tm_mon=2, tm_mday=4, tm_hour=4, tm_min=31,
tm_sec=3, tm_wday=1, tm_yday=35, tm_isdst=0)
In my (Central) time zone, 22:31 was 04:31 of the next day in UTC (formerly called Greenwich time or Zulu time).
If you omit the argument to localtime()
or gmtime()
, they assume the current time.
The opposite of these is mktime()
, which converts
a struct_time
object to epoch seconds:
>>>
tm
=
time
.
localtime
(
now
)
>>>
time
.
mktime
(
tm
)
1391488263.0
This doesn’t exactly match our earlier epoch value of now()
because
the struct_time
object preserves time only to the second.
Some advice: wherever possible, use UTC instead of time zones. UTC is an absolute time, independent of time zones. If you have a server, set its time to UTC; do not use local time.
Here’s some more advice (free of charge, no less): never use daylight savings time if you can avoid it. If you use daylight savings time, an hour disappears at one time of year (“spring ahead”) and occurs twice at another time (“fall back”). For some reason, many organizations use daylight savings in their computer systems, but are mystified every year by data duplicates and dropouts. It all ends in tears.
Remember, your friends are UTC for times, and UTF-8 for strings (for more about UTF-8, see Chapter 7).
isoformat()
is not the only way to write dates and times.
You already saw the ctime()
function in the time
module, which you can use to convert epochs
to strings:
>>>
import
time
>>>
now
=
time
.
time
()
>>>
time
.
ctime
(
now
)
'Mon Feb 3 21:14:36 2014'
You can also convert dates and times to strings by using strftime()
.
This is provided as a method in the datetime
, date
, and time
objects,
and as a function in the time
module.
strftime()
uses format strings to specify the output, which you can see in Table 10-1.
Format string | Date/time unit | Range |
---|---|---|
|
year |
|
|
month |
|
|
month name |
|
|
month abbrev |
|
|
day of month |
|
|
weekday name |
|
|
weekday abbrev |
|
|
hour (24 hr) |
|
|
hour (12 hr) |
|
|
AM/PM |
|
|
minute |
|
|
second |
|
Numbers are zero-padded on the left.
Here’s the strftime()
function provided by the time
module. It
converts a struct_time
object to a string.
We’ll first define the format string fmt
and use it again later:
>>>
import
time
>>>
fmt
=
"It's %A, %B
%d
, %Y, local time %I:%M:%S%p"
>>>
t
=
time
.
localtime
()
>>>
t
time.struct_time(tm_year=2014, tm_mon=2, tm_mday=4, tm_hour=19,
tm_min=28, tm_sec=38, tm_wday=1, tm_yday=35, tm_isdst=0)
>>>
time
.
strftime
(
fmt
,
t
)
"It's Tuesday, February 04, 2014, local time 07:28:38PM"
If we try this with a date
object, only the date parts will work,
and the time defaults to midnight:
>>>
from
datetime
import
date
>>>
some_day
=
date
(
2014
,
7
,
4
)
>>>
fmt
=
"It's %B
%d
, %Y, local time %I:%M:%S%p"
>>>
some_day
.
strftime
(
fmt
)
"It's Friday, July 04, 2014, local time 12:00:00AM"
For a time
object, only the time parts are converted:
>>>
from
datetime
import
time
>>>
some_time
=
time
(
10
,
35
)
>>>
some_time
.
strftime
(
fmt
)
"It's Monday, January 01, 1900, local time 10:35:00AM"
Clearly, you won’t want to use the day parts from a time
object,
because they’re meaningless.
To go the other way and convert a string to a date or time,
use strptime()
with the same format string.
There’s no regular expression pattern matching;
the nonformat parts of the string (without %
) need to match exactly.
Let’s specify a format that matches year-month-day,
such as 2012-01-29
.
What happens if the date string you want to parse has spaces instead of dashes?
>>>
import
time
>>>
fmt
=
"%Y-%m-
%d
"
>>>
time
.
strptime
(
"2012 01 29"
,
fmt
)
Traceback (most recent call last):
File"<stdin>"
, line1
, in<module>
File"/Library/Frameworks/Python.framework/Versions/3.3/lib/
python3.3/_strptime.py"
, line494
, in_strptime_time
tt
=
_strptime
(
data_string
,
format
)[
0
]
File"/Library/Frameworks/Python.framework/Versions/3.3/lib/
python3.3/_strptime.py"
, line337
, in_strptime
(
data_string
,
format
))
ValueError
:time data '2012 01 29' does not match format '%Y-%m-%d'
If we feed strptime()
some dashes, is it happy now?
>>>
time
.
strptime
(
"2012-01-29"
,
fmt
)
time.struct_time(tm_year=2012, tm_mon=1, tm_mday=29, tm_hour=0, tm_min=0,
tm_sec=0, tm_wday=6, tm_yday=29, tm_isdst=-1)
Yes.
Even if the string seems to match its format, an exception is raised if a value is out of range:
>>>
time
.
strptime
(
"2012-13-29"
,
fmt
)
Traceback (most recent call last):
File"<stdin>"
, line1
, in<module>
File"/Library/Frameworks/Python.framework/Versions/3.3/lib/
python3.3/_strptime.py"
, line494
, in_strptime_time
tt
=
_strptime
(
data_string
,
format
)[
0
]
File"/Library/Frameworks/Python.framework/Versions/3.3/lib/
python3.3/_strptime.py"
, line337
, in_strptime
(
data_string
,
format
))
ValueError
:time data '2012-13-29' does not match format '%Y-%m-%d'
Names are specific to your locale—internationalization settings for your operating system.
To print different month and day names,
change your locale by using setlocale()
;
its first argument is
locale.LC_TIME
for dates and times,
and the second is a string
combining the language and country abbreviation.
Let’s invite some international friends to
a Halloween party. We’ll print the month, day,
and day of week in
US English, French, German,
Spanish, and Icelandic. (What? You think Icelanders don’t enjoy a good party as much as anyone else? They even have real elves.)
>>>
import
locale
>>>
from
datetime
import
date
>>>
halloween
=
date
(
2014
,
10
,
31
)
>>>
for
lang_country
in
[
'en_us'
,
'fr_fr'
,
'de_de'
,
'es_es'
,
'is_is'
,]:
...
locale
.
setlocale
(
locale
.
LC_TIME
,
lang_country
)
...
halloween
.
strftime
(
'%A, %B
%d
'
)
...
'en_us'
'Friday, October 31'
'fr_fr'
'Vendredi, octobre 31'
'de_de'
'Freitag, Oktober 31'
'es_es'
'viernes, octubre 31'
'is_is'
'föstudagur, október 31'
>>>
Where do you find these magic values for lang_country
?
This is a bit wonky, but you can try this to get all of them
(there are a few hundred):
>>>
import
locale
>>>
names
=
locale
.
locale_alias
.
keys
()
From names
,
let’s get just locale names that seem to work
with setlocale()
,
such as the ones we used in the preceding
example—a two-character language
code followed by an underscore and a two-character
country code:
>>>
good_names
=
[
name
for
name
in
names
if
len(name) == 5 and name[2] == '_']
What do the first five look like?
>>>
good_names
[:
5
]
['sr_cs', 'de_at', 'nl_nl', 'es_ni', 'sp_yu']
So, if you wanted all the German language locales, try this:
>>>
de
=
[
name
for
name
in
good_names
if
name
.
startswith
(
'de'
)]
>>>
de
['de_at', 'de_de', 'de_ch', 'de_lu', 'de_be']
10.1 Write the current date as a string to the text file today.txt.
10.2 Read the text file today.txt into the string today_string
.
10.3 Parse the date from today_string
.
10.4 List the files in your current directory.
10.5 List the files in your parent directory.
10.6 Use multiprocessing to create three separate processes. Make each one wait a random number of seconds between one and five, print the current time, and then exit.
10.7 Create a date object of your day of birth.
10.8 What day of the week was your day of birth?
10.9 When will you be (or when were you) 10,000 days old?
1 This starting point is roughly when Unix was born.