Basics, import.
This one is simpler than you may think. When you’re done, your
file and interaction should look close to the following code;
remember that Python can read a whole file into a string or lines
list, and the len
built-in returns the length of
strings and lists:
%cat mymod.py
def countLines(name): file = open(name, 'r') return len(file.readlines()) def countChars(name): return len(open(name, 'r').read()) def test(name): # or pass file object return countLines(name), countChars(name) # or return a dictionary %python
>>>import mymod
>>>mymod.test('mymod.py')
(10, 291)
On Unix, you can verify your output with a wc
command. Incidentally, to do the “ambitious” part
(passing in a file object, so you only open the file once),
you’ll probably need to use the seek
method
of the built-in file object. We didn’t cover it in the text,
but it works just like C’s fseek
call (and
calls it behind the scenes); seek
resets the
current position in the file to an offset passed in. To rewind to the
start of a file without closing and reopening, call
file.seek (0 ); the file read methods all pick
up at the current position in the file, so you need to rewind to
reread. Here’s what this tweak would look like:
%cat mymod2.py
def countLines(file): file.seek(0) # rewind to start of file return len(file.readlines()) def countChars(file): file.seek(0) # ditto (rewind if needed) return len(file.read()) def test(name): file = open(name, 'r') # pass file object return countLines(file), countChars(file) # only open file once >>>import mymod2
>>>mymod2.test("mymod2.py")
(11, 392)
from/from*.
Here’s the from
* bit;
replace *
with countChars
to do
the rest:
%python
>>>from mymod import *
>>>countChars("mymod.py")
291
__main__. If you code it properly, it works in either mode (program run or module import):
%cat mymod.py
def countLines(name): file = open(name, 'r') return len(file.readlines()) def countChars(name): return len(open(name, 'r').read()) def test(name): # or pass file object return countLines(name), countChars(name) # or return a dictionary if __name__ == '__main__': print test('mymod.py') %python mymod.py
(13, 346)
Nested imports. Our solution for this appears below:
%cat myclient.py
from mymod import countLines from mymod import countChars print countLines('mymod.py'), countChars('mymod.py') %python myclient.py
13 346
As for the rest of this one: mymod ’s
functions are accessible (that is, importable) from the top level of
myclient, since from assigns just to names in the importer
(it’s as if mymod
’s
def
s appeared in myclient).
If myclient used import, you’d need to use
a path to get to the functions in mymod
from
myclient (for instance,
myclient.mymod.countLines
). In fact,
you can define collector modules that import all
the names from other modules, so they’re available in a single
convenience module. Using the following code, you wind up with three
different copies of name somename
:
mod1.somename
,
collector.somename
, and _
_main
__.somename
; all three
share the same integer object initially.
%cat mod1.py
somename = 42 %cat collector.py
from mod1 import * # collect lots of names here from mod2 import * # from assigns to my names from mod3 import * >>>from collector import somename
Reload. This exercise just asks you to experiment with changing the changer.py example in the book, so there’s not much for us to show here. If you had some fun with it, give yourself extra points.
Circular imports. The short story is that importing
recur2
first works, because the
recursive import then happens at the
import
in recur1
, not at a
from
in recur2
. The long story
goes like this: importing recur2
first works,
because the recursive import from recur1
to
recur2
fetches recur2
as a
whole, instead of getting specific names. recur2
is incomplete when imported from recur1
, but
because it uses import
instead of
from
, you’re safe: Python finds and returns
the already created recur2
module object and
continues to run the rest of recur1
without a
glitch. When the recur2
import resumes, the second
from
finds name Y
in
recur1
(it’s been run completely), so no
error is reported. Running a file as a script is not the same as
importing it as a module; these cases are the same as running the
first import
or from
in the
script interactively. For instance, running recur1
as a script is the same as importing recur2
interactively, since recur2
is the first module
imported in recur1
. (E-I-E-I-O!)