Skip to content

Commit

Permalink
Second edition, first upload
Browse files Browse the repository at this point in the history
  • Loading branch information
madscheme committed Mar 22, 2020
1 parent 240de58 commit 9916d83
Show file tree
Hide file tree
Showing 189 changed files with 1,115 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
*.pyc
26 changes: 26 additions & 0 deletions 1st_edition/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Introducing Python
=================

This repository contains the programs featured in _Introducing Python_.
Some examples have been updated for the second and third printings.

|directory|chapter|
|---|---|
|[intro](intro)| 1. A taste of Py
| | 2. Py ingredients: numbers, strings, and variables
| | 3. Py filling: lists, tuples, dictionaries, and sets
| | 4. Py crust: code structures
|[boxes](boxes)| 5. Py boxes: modules, packages, and programs
| | 6. Oh oh: objects and classes
| | 7. Mangle data like a pro
|[storage](storage)|8. Data has to go somewhere
|[web](web) | 9. The web, untangled
|[sys](sys) | 10. Systems
|[net](net) | 11. Concurrency and networks
|[dev](dev) | 12. Be a pythonista
|[art](art) | A. Py art
|[bus](bus) | B. Py at work
| | C. Py sci
| | D. Install Python 3
| | E. Answers to exercises
| | F. Cheatsheets
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
27 changes: 3 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,5 @@
Introducing Python
Introducing Python -- Second Edition
=================

This repository contains the programs featured in _Introducing Python_.
Some examples have been updated for the second and third printings.

|directory|chapter|
|---|---|
|[intro](intro)| 1. A taste of Py
| | 2. Py ingredients: numbers, strings, and variables
| | 3. Py filling: lists, tuples, dictionaries, and sets
| | 4. Py crust: code structures
|[boxes](boxes)| 5. Py boxes: modules, packages, and programs
| | 6. Oh oh: objects and classes
| | 7. Mangle data like a pro
|[storage](storage)|8. Data has to go somewhere
|[web](web) | 9. The web, untangled
|[sys](sys) | 10. Systems
|[net](net) | 11. Concurrency and networks
|[dev](dev) | 12. Be a pythonista
|[art](art) | A. Py art
|[bus](bus) | B. Py at work
| | C. Py sci
| | D. Install Python 3
| | E. Answers to exercises
| | F. Cheatsheets
This repository contains the programs featured in
the second edition of the book _Introducing Python_.
19 changes: 19 additions & 0 deletions ch01/archive.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import webbrowser
import json
from urllib.request import urlopen

print("Let's find an old website.")
site = input("Type a website URL: ")
era = input("Type a year, month, and day, like 20150613: ")
url = "http://archive.org/wayback/available?url=%s&timestamp=%s" % (site, era)
response = urlopen(url)
contents = response.read()
text = contents.decode("utf-8")
data = json.loads(text)
try:
old_site = data["archived_snapshots"]["closest"]["url"]
print("Found this copy: ", old_site)
print("It should appear in your browser now.")
webbrowser.open(old_site)
except:
print("Sorry, no luck finding", site)
16 changes: 16 additions & 0 deletions ch01/archive2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import webbrowser
import requests

print("Let's find an old website.")
site = input("Type a website URL: ")
era = input("Type a year, month, and day, like 20150613: ")
url = "http://archive.org/wayback/available?url=%s&timestamp=%s" % (site, era)
response = requests.get(url)
data = response.json()
try:
old_site = data["archived_snapshots"]["closest"]["url"]
print("Found this copy: ", old_site)
print("It should appear in your browser now.")
webbrowser.open(old_site)
except:
print("Sorry, no luck finding", site)
2 changes: 2 additions & 0 deletions ch01/countdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
for countdown in 5, 4, 3, 2, 1, "hey!":
print(countdown)
7 changes: 7 additions & 0 deletions ch01/quotes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
quotes = {
"Moe": "A wise guy, huh?",
"Larry": "Ow!",
"Curly": "Nyuk nyuk!",
}
stooge = "Curly"
print(stooge, "says:", quotes[stooge])
9 changes: 9 additions & 0 deletions ch01/spells.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
spells = [
"Riddikulus!",
"Wingardium Leviosa!",
"Avada Kedavra!",
"Expecto Patronum!",
"Nox!",
"Lumos!",
]
print(spells[3])
5 changes: 5 additions & 0 deletions ch05/poem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
poem = '''There was a Young Lady of Norway,
Who casually sat in a doorway;
When the door squeezed her flat,
She exclaimed, "What of that?"
This courageous Young Lady of Norway.'''
5 changes: 5 additions & 0 deletions ch05/poem2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
poem2 = '''I do not like thee, Doctor Fell.
The reason why, I cannot tell.
But this I know, and know full well:
I do not like thee, Doctor Fell.
'''
6 changes: 6 additions & 0 deletions ch05/poem3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
poem = '''All that doth flow we cannot liquid name
Or else would fire and water be the same;
But that is liquid which is moist and wet
Fire that property can never get.
Then 'tis not cold that doth the fire put out
But 'tis the wet that makes it die, no doubt.'''
7 changes: 7 additions & 0 deletions ch11/choices/advice.oy
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from random import choice

answers = ["Yes!", "No!", "Reply hazy", "Sorry, what?"]

def give():
"""Return random advice"""
return choice(answers)
8 changes: 8 additions & 0 deletions ch11/choices/fast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from random import choice

places = ["McDonalds", "KFC", "Burger King", "Taco Bell",
"Wendys", "Arbys", "Pizza Hut"]

def pick():
"""Return random fast food place"""
return choice(places)
8 changes: 8 additions & 0 deletions ch11/fast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from random import choice

places = ["McDonalds", "KFC", "Burger King", "Taco Bell",
"Wendys", "Arbys", "Pizza Hut"]

def pick(): # see the docstring below?
"""Return random fast food place"""
return choice(places)
6 changes: 6 additions & 0 deletions ch11/fast2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
places = ["McDonalds", "KFC", "Burger King", "Taco Bell",
"Wendys", "Arbys", "Pizza Hut"]

def pick():
import random
return random.choice(places)
4 changes: 4 additions & 0 deletions ch11/fast3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import fast as f

place = f.pick()
print("Let's go to", place)
4 changes: 4 additions & 0 deletions ch11/fast4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from fast import pick

place = pick()
print("Let's go to", place)
4 changes: 4 additions & 0 deletions ch11/fast5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from fast import pick as who_cares

place = who_cares()
print("Let's go to", place)
4 changes: 4 additions & 0 deletions ch11/lunch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import fast

place = fast.pick()
print("Let's go to", place)
4 changes: 4 additions & 0 deletions ch11/questions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from fast import pick as who_cares

place = who_cares()
print("Let's go to", place)
24 changes: 24 additions & 0 deletions ch12/mammoth.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
We have seen thee, queen of cheese,
Lying quietly at your ease,
Gently fanned by evening breeze,
Thy fair form no flies dare seize.
All gaily dressed soon you'll go
To the great Provincial show,
To be admired by many a beau
In the city of Toronto.
Cows numerous as a swarm of bees,
Or as the leaves upon the trees,
It did require to make thee please,
And stand unrivalled, queen of cheese.
May you not receive a scar as
We have heard that Mr. Harris
Intends to send you off as far as
The great world's show at Paris.
Of the youth beware of these,
For some of them might rudely squeeze
And bite your cheek, then songs or glees
We could not sing, oh! queen of cheese.
We'rt thou suspended from balloon,
You'd cast a shade even at noon,
Folks would think it was the moon
About to fall and crush them soon.
35 changes: 35 additions & 0 deletions ch14/convert_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from io import BytesIO
from PIL import Image
import sys

def data_to_img(data):
"""Return PIL Image object, with data from in-memory <data>"""
fp = BytesIO(data)
return Image.open(fp) # reads from memory

def img_to_data(img, fmt=None):
"""Return image data from PIL Image <img>, in <fmt> format"""
fp = BytesIO()
if not fmt:
fmt = img.format # keeps the original format
img.save(fp, fmt) # writes to memory
return fp.getvalue()

def convert_image(data, fmt=None):
"""Convert image <data> to PIL <fmt> image data"""
img = data_to_img(data)
return img_to_data(img, fmt)

def get_file_data(name):
"""Return PIL Image object for image file <name>"""
img = Image.open(name)
print("img", img, img.format)
return img_to_data(img)

if __name__ == "__main__":
for name in sys.argv[1:]:
data = get_file_data(name)
print("in", len(data), data[:10])
for fmt in ("gif", "png", "jpeg"):
out_data = convert_image(data, fmt)
print("out", len(out_data), out_data[:10])
35 changes: 35 additions & 0 deletions ch15/cf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from concurrent import futures
import math
import time
import sys

def calc(val):
time.sleep(1)
result = math.sqrt(float(val))
return result

def use_threads(num, values):
t1 = time.time()
with futures.ThreadPoolExecutor(num) as tex:
results = tex.map(calc, values)
t2 = time.time()
return t2 - t1

def use_processes(num, values):
t1 = time.time()
with futures.ProcessPoolExecutor(num) as pex:
results = pex.map(calc, values)
t2 = time.time()
return t2 - t1

def main(workers, values):
print(f"Using {workers} workers for {len(values)} values")
t_sec = use_threads(workers, values)
print(f"Threads took {t_sec:.4f} seconds")
p_sec = use_processes(workers, values)
print(f"Processes took {p_sec:.4f} seconds")

if __name__ == '__main__':
workers = int(sys.argv[1])
values = list(range(1, 6)) # 1 .. 5
main(workers, values)
35 changes: 35 additions & 0 deletions ch15/cf2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from concurrent import futures
import math
import sys

def calc(val):
result = math.sqrt(float(val))
return val, result

def use_threads(num, values):
with futures.ThreadPoolExecutor(num) as tex:
tasks = [tex.submit(calc, value) for value in values]
for f in futures.as_completed(tasks):
yield f.result()

def use_processes(num, values):
with futures.ProcessPoolExecutor(num) as pex:
tasks = [pex.submit(calc, value) for value in values]
for f in futures.as_completed(tasks):
yield f.result()

def main(workers, values):
print(f"Using {workers} workers for {len(values)} values")
print("Using threads:")
for val, result in use_threads(workers, values):
print(f'{val} {result:.4f}')
print("Using processes:")
for val, result in use_processes(workers, values):
print(f'{val} {result:.4f}')

if __name__ == '__main__':
workers = 3
if len(sys.argv) > 1:
workers = int(sys.argv[1])
values = list(range(1, 6)) # 1 .. 5
main(workers, values)
20 changes: 20 additions & 0 deletions ch15/dishes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import multiprocessing as mp

def washer(dishes, output):
for dish in dishes:
print('Washing', dish, 'dish')
output.put(dish)

def dryer(input):
while True:
dish = input.get()
print('Drying', dish, 'dish')
input.task_done()

dish_queue = mp.JoinableQueue()
dryer_proc = mp.Process(target=dryer, args=(dish_queue,))
dryer_proc.daemon = True
dryer_proc.start()
dishes = ['salad', 'bread', 'entree', 'dessert']
washer(dishes, dish_queue)
dish_queue.join()
10 changes: 10 additions & 0 deletions ch15/gevent_monkey.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import gevent
from gevent import monkey; monkey.patch_all()
import socket

hosts = ['www.crappytaxidermy.com', 'www.walterpottertaxidermy.com',
'www.antique-taxidermy.com']
jobs = [gevent.spawn(socket.gethostbyname, host) for host in hosts]
gevent.joinall(jobs, timeout=5)
for job in jobs:
print(job.value)
9 changes: 9 additions & 0 deletions ch15/gevent_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import gevent
from gevent import socket

hosts = ['www.crappytaxidermy.com', 'www.walterpottertaxidermy.com',
'www.antique-taxidermy.com']
jobs = [gevent.spawn(gevent.socket.gethostbyname, host) for host in hosts]
gevent.joinall(jobs, timeout=5)
for job in jobs:
print(job.value)
25 changes: 25 additions & 0 deletions ch15/knock_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from twisted.internet import reactor, protocol

class KnockClient(protocol.Protocol):

def connectionMade(self):
self.transport.write("Knock knock")

def dataReceived(self, data):
if data.startswith("Who's there?"):
response = "Disappearing client"
self.transport.write(response)
else:
self.transport.loseConnection()
reactor.stop()

class KnockFactory(protocol.ClientFactory):
protocol = KnockClient

def main():
f = KnockFactory()
reactor.connectTCP("localhost", 8000, f)
reactor.run()

if __name__ == '__main__':
main()
Loading

0 comments on commit 9916d83

Please sign in to comment.