├── .gitignore
├── README.md
├── code
├── Appendix A
│ ├── backers.csv
│ ├── book_maker.py
│ ├── book_maker2.py
│ ├── book_maker3.py
│ ├── csv_reader.py
│ └── send_email.py
├── Chapter 10 - Functions
│ ├── add.py
│ ├── args_and_kwargs.py
│ ├── kw_func.py
│ ├── kw_func2.py
│ ├── scope.py
│ ├── scope2.py
│ ├── simple_function.py
│ └── stub.py
├── Chapter 11 - Classes
│ ├── car_subclass.py
│ ├── simple_class_2.x.py
│ ├── simple_class_3.x.py
│ ├── vehicle.py
│ └── vehicle2.py
├── Chapter 12 - Introspection
│ └── readme.txt
├── Chapter 13 - csv
│ ├── TB_data_dictionary_2014-02-26.csv
│ ├── csv_dictwriter.py
│ ├── csv_reader.py
│ ├── csv_reader2.py
│ ├── csv_writer.py
│ └── data.csv
├── Chapter 14 - configparser
│ ├── create_config.py
│ ├── crud_config.py
│ ├── crud_config_refactored.py
│ └── interpolation.py
├── Chapter 15 - logging
│ ├── exception_logger.py
│ ├── log_multiple_modules.py
│ ├── log_multiple_modules2.py
│ ├── log_with_config.py
│ ├── log_with_config2.py
│ ├── logging.conf
│ ├── otherMod.py
│ ├── otherMod2.py
│ └── simple_logger.py
├── Chapter 16 - os
│ └── readme.txt
├── Chapter 17 - smtplib and email
│ ├── email.ini
│ ├── send_email.py
│ ├── send_email_attachment.py
│ ├── send_email_function.py
│ ├── send_multiple_emails.py
│ ├── send_to_cc_bcc.py
│ └── smtp_config.py
├── Chapter 18 - sqlite
│ ├── basic_queries.py
│ ├── create_database.py
│ ├── delete_record.py
│ └── update_database.py
├── Chapter 19 - subprocess
│ ├── communicate_example.py
│ └── readme.txt
├── Chapter 2 - Strings
│ ├── creating_strings.py
│ ├── string_concatenation.py
│ ├── string_methods.py
│ ├── string_slicing.py
│ └── string_substitution.py
├── Chapter 20 - sys
│ ├── call_exit.py
│ ├── exit.py
│ ├── readme.txt
│ └── sysargv.py
├── Chapter 21 - threading
│ ├── downloader_2x.py
│ ├── downloader_3x.py
│ ├── downloader_queues.py
│ └── simple_threads.py
├── Chapter 22 - time
│ └── readme.txt
├── Chapter 23 - xml
│ ├── appt.xml
│ ├── create_with_elementtree.py
│ ├── edit_with_elementtree.py
│ ├── example.xml
│ ├── minidom_parse.py
│ ├── minidom_parse2.py
│ ├── original_appt.xml
│ └── parse_with_elementtree.py
├── Chapter 24 - pdb
│ └── debug_test.py
├── Chapter 25 - decorators
│ ├── add_property.py
│ ├── add_property_setter.py
│ ├── builtin_decorators.py
│ ├── logging_decorator.py
│ ├── properties.py
│ ├── property_setters_getters.py
│ ├── simple_decorator.py
│ ├── simple_decorator2.py
│ └── simple_function.py
├── Chapter 26 - lambda
│ ├── simple_lambda.py
│ └── tkinter_lambda.py
├── Chapter 27 - profiling
│ └── ptest.py
├── Chapter 28 - testing
│ ├── dtest1.py
│ ├── dtest2.py
│ ├── first_test_bowling.py
│ ├── first_test_bowling2.py
│ ├── game_v2.py
│ ├── second_test_bowling.py
│ ├── second_test_bowling2.py
│ └── third_test_bowling.py
├── Chapter 29 - installing modules
│ └── readme.txt
├── Chapter 3 - Lists Dicts Tuples
│ ├── dict_examples.py
│ ├── list_examples.py
│ └── tuple_examples.py
├── Chapter 30 - configobj
│ ├── config.ini
│ ├── configobj_example.py
│ └── configspec_example.py
├── Chapter 31 - lxml
│ ├── create_xml_with_objectify.py
│ ├── example.xml
│ ├── example2.xml
│ ├── parse_book_example.py
│ ├── parse_book_example_refactored.py
│ ├── parse_with_objectify.py
│ └── simple_parser.py
├── Chapter 32 - code analysis
│ ├── crummy_code.py
│ └── crummy_code_fixed.py
├── Chapter 33 - requests
│ ├── submit_form_requests.py
│ └── submit_form_urllib.py
├── Chapter 34 - SQLAlchemy
│ ├── add_data.py
│ ├── deleting_data.py
│ ├── modify_data.py
│ ├── queries.py
│ └── table_def.py
├── Chapter 35 - virtualenv
│ └── readme.txt
├── Chapter 36 - creating modules and packages
│ ├── arithmetic.py
│ ├── arithmetic2.py
│ ├── modify_path.py
│ ├── mymath
│ │ ├── __init__.py
│ │ ├── add.py
│ │ ├── adv
│ │ │ ├── __init__.py
│ │ │ └── sqrt.py
│ │ ├── divide.py
│ │ ├── multiply.py
│ │ └── subtract.py
│ └── setup.py
├── Chapter 37 - add your code to pypi
│ ├── .pypirc
│ ├── setup.py
│ └── setup2.py
├── Chapter 38 - Python eggs
│ └── setup.py
├── Chapter 39 - Python wheels
│ └── readme.txt
├── Chapter 4 - Conditionals
│ └── conditionals.py
├── Chapter 40 - py2exe
│ ├── advanced_setup.py
│ ├── sampleApp.py
│ └── setup.py
├── Chapter 41 - bbfreeze
│ ├── bb_setup.py
│ ├── bb_setup2.py
│ ├── config_1.py
│ └── sampleApp.py
├── Chapter 42 - cx_Freeze
│ ├── config_1.py
│ ├── sampleApp.py
│ ├── setup.py
│ └── setup2.py
├── Chapter 43 - PyInstaller
│ ├── config_1.py
│ └── sampleApp.py
├── Chapter 44 - Creating an installer
│ └── sampleApp.py
├── Chapter 5 - Loops
│ ├── for_loops.py
│ └── while_loops.py
├── Chapter 6 - Comprehensions
│ └── comprehensions.py
├── Chapter 7 - Exceptions
│ └── exceptions.py
├── Chapter 8 - Working with Files
│ ├── catching_errors.py
│ ├── file_io.py
│ ├── open_and_close.py
│ ├── open_and_close2.py
│ ├── open_and_close3.py
│ ├── open_with.py
│ ├── read_in_chunks.py
│ ├── read_line_by_line.py
│ ├── test.txt
│ └── write_file.py
└── Chapter 9 - Imports
│ └── readme.txt
└── manuscript
├── Book.txt
├── Sample.txt
├── appendix_a.txt
├── chapter1.txt
├── chapter10.txt
├── chapter11.txt
├── chapter12.txt
├── chapter13.txt
├── chapter14.txt
├── chapter15.txt
├── chapter16.txt
├── chapter17.txt
├── chapter18.txt
├── chapter19.txt
├── chapter2.txt
├── chapter20.txt
├── chapter21.txt
├── chapter22.txt
├── chapter23.txt
├── chapter24.txt
├── chapter25.txt
├── chapter26.txt
├── chapter27.txt
├── chapter28.txt
├── chapter29.txt
├── chapter3.txt
├── chapter30.txt
├── chapter31.txt
├── chapter32.txt
├── chapter33.txt
├── chapter34.txt
├── chapter35.txt
├── chapter36.txt
├── chapter37.txt
├── chapter38.txt
├── chapter39.txt
├── chapter4.txt
├── chapter40.txt
├── chapter41.txt
├── chapter42.txt
├── chapter43.txt
├── chapter44.txt
├── chapter5.txt
├── chapter6.txt
├── chapter7.txt
├── chapter8.txt
├── chapter9.txt
├── images
├── appendix_1.jpg
├── barcode.jpg
├── bb_config.jpg
├── call_exit.jpg
├── cx_config.jpg
├── doctest.jpg
├── doctest_error.jpg
├── doctest_from_file.jpg
├── doctest_from_file_intepreter.jpg
├── gui2exe.jpg
├── idle_code_colors.jpg
├── idle_editor.jpg
├── idle_main.jpg
├── inno_setup_1.jpg
├── inno_setup_2.jpg
├── inno_setup_3.jpg
├── inno_welcome.jpg
├── mousecovertitlejpg_sm.jpg
├── part_1.jpg
├── part_2.jpg
├── part_3.jpg
├── part_4.jpg
├── part_5.jpg
├── path_browser.jpg
├── pdb_step.jpg
├── py2exe_output.jpg
├── py2exe_wx.jpg
├── pyinstaller.jpg
├── sys_argv.jpg
├── title_page.png
└── wheel_creation.jpg
├── intro.txt
├── part_1_picture.txt
├── part_2_picture.txt
├── part_3_picture.txt
├── part_4_picture.txt
├── part_5_picture.txt
├── part_i.txt
├── part_ii.txt
├── part_iii.txt
├── part_iv.txt
└── part_v.txt
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.pyc
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Python 101 Community Edition is the free and open source version of my first book, [Python 101](https://leanpub.com/python_101)
2 |
3 | You can also read the book online at [www.Python101.org](www.Python101.org)
4 |
5 | [
](https://leanpub.com/python_101)
6 |
7 | **There is a second edition of Python 101 that is scheduled to come out in Fall 2020. Learn more on [Kickstarter](https://www.kickstarter.com/projects/driscollis/python-101-2nd-edition)**
8 |
--------------------------------------------------------------------------------
/code/Appendix A/backers.csv:
--------------------------------------------------------------------------------
1 | Mike Driscoll,test@py.com
2 | Andy Hunter,andwa@hunter.org
3 | Toby Mac,macdaddy@gotee.com
--------------------------------------------------------------------------------
/code/Appendix A/book_maker.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 |
4 | chapters = ['chapter_1.rst',
5 | 'chapter_2.rst',
6 | 'chapter_3.rst']
7 |
8 | def read_chapter(chapter):
9 | """
10 | Reads a chapter and returns the stream
11 | """
12 | path = os.path.join("data", chapter)
13 | try:
14 | with open(path) as chp_handler:
15 | data = chp_handler.read()
16 | except (IOError, OSError):
17 | raise Exception("Unable to open chapter: %s" % chapter)
18 | return data
19 |
20 | def make_book(name="Mike", email_address="test@py.com"):
21 | """
22 | Creates Python 101 book
23 | """
24 | book_path = "output/python101.rst"
25 | pdf_path = "output/python101.pdf"
26 | page_break = """
27 | .. raw:: pdf
28 |
29 | PageBreak
30 | """
31 | footer = """
32 | .. footer::
33 |
34 | Copyright |copy| 2014 by Michael Driscoll, all rights reserved.
35 | Licensed to %s <%s>
36 |
37 | .. |copy| unicode:: 0xA9 .. copyright sign
38 | """ % (name, email_address)
39 | try:
40 | with open(book_path, "w") as book:
41 | book.write(footer + "\n")
42 | for chapter in chapters:
43 | data = read_chapter(chapter)
44 | book.write(data)
45 | book.write("\n")
46 | book.write(page_break + "\n")
47 | except:
48 | print("Error writing book!")
49 | raise
50 |
51 | cmd = [r"C:\Python27\Scripts\rst2pdf.exe",
52 | book_path, "-o", pdf_path]
53 | subprocess.call(cmd)
54 |
55 | if __name__ == "__main__":
56 | make_book()
--------------------------------------------------------------------------------
/code/Appendix A/book_maker2.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import os
3 | import subprocess
4 |
5 | chapters = ['chapter_1.rst',
6 | 'chapter_2.rst',
7 | 'chapter_3.rst']
8 |
9 | def read_chapter(chapter):
10 | """
11 | Reads a chapter and returns the stream
12 | """
13 | path = os.path.join("data", chapter)
14 | try:
15 | with open(path) as chp_handler:
16 | data = chp_handler.read()
17 | except (IOError, OSError):
18 | raise Exception("Unable to open chapter: %s" % chapter)
19 | return data
20 |
21 | def make_book(name="Mike", email_address="test@py.com"):
22 | """
23 | Creates Python 101 book
24 | """
25 | book_path = "output/python101.rst"
26 | pdf_path = "output/python101.pdf"
27 | page_break = """
28 | .. raw:: pdf
29 |
30 | PageBreak
31 | """
32 | footer = """
33 | .. footer::
34 |
35 | Copyright |copy| 2014 by Michael Driscoll, all rights reserved.
36 | Licensed to %s <%s>
37 |
38 | .. |copy| unicode:: 0xA9 .. copyright sign
39 | """ % (name, email_address)
40 | try:
41 | with open(book_path, "w") as book:
42 | book.write(footer + "\n")
43 | for chapter in chapters:
44 | data = read_chapter(chapter)
45 | book.write(data)
46 | book.write("\n")
47 | book.write(page_break + "\n")
48 | except:
49 | print("Error writing book!")
50 | raise
51 |
52 | cmd = [r"C:\Python27\Scripts\rst2pdf.exe",
53 | book_path, "-o", pdf_path]
54 | subprocess.call(cmd)
55 |
56 | def main(path):
57 | """"""
58 | try:
59 | with open(path) as csv_file:
60 | reader = csv.reader(csv_file)
61 | for line in reader:
62 | name, email = line
63 | make_book(name, email)
64 | except IOError:
65 | print("Error reading file: %s" % path)
66 | raise
67 |
68 | if __name__ == "__main__":
69 | main("backers.csv")
--------------------------------------------------------------------------------
/code/Appendix A/book_maker3.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import os
3 | import smtplib
4 | import subprocess
5 |
6 | from email import encoders
7 | from email.mime.text import MIMEText
8 | from email.mime.base import MIMEBase
9 | from email.mime.multipart import MIMEMultipart
10 | from email.utils import formatdate
11 |
12 | chapters = ['chapter_1.rst',
13 | 'chapter_2.rst',
14 | 'chapter_3.rst']
15 |
16 | def make_book(name="Mike", email_address="test@py.com"):
17 | """
18 | Creates Python 101 book
19 | """
20 | book_path = "output/python101.rst"
21 | pdf_path = "output/python101.pdf"
22 | page_break = """
23 | .. raw:: pdf
24 |
25 | PageBreak
26 | """
27 | footer = """
28 | .. footer::
29 |
30 | Copyright |copy| 2014 by Michael Driscoll, all rights reserved.
31 | Licensed to %s <%s>
32 |
33 | .. |copy| unicode:: 0xA9 .. copyright sign
34 | """ % (name, email_address)
35 | try:
36 | with open(book_path, "w") as book:
37 | book.write(footer + "\n")
38 | for chapter in chapters:
39 | data = read_chapter(chapter)
40 | book.write(data)
41 | book.write("\n")
42 | book.write(page_break + "\n")
43 | except:
44 | print("Error writing book!")
45 | raise
46 |
47 | cmd = [r"C:\Python27\Scripts\rst2pdf.exe",
48 | book_path, "-o", pdf_path]
49 | subprocess.call(cmd)
50 | return pdf_path
51 |
52 | def read_chapter(chapter):
53 | """
54 | Reads a chapter and returns the stream
55 | """
56 | path = os.path.join("data", chapter)
57 | try:
58 | with open(path) as chp_handler:
59 | data = chp_handler.read()
60 | except (IOError, OSError):
61 | raise Exception("Unable to open chapter: %s" % chapter)
62 | return data
63 |
64 | def send_email(email, pdf):
65 | """
66 | Send an email out
67 | """
68 | header0 = 'Content-Disposition'
69 | header1 ='attachment; filename="%s"' % os.path.basename(pdf)
70 | header = header0, header1
71 |
72 | host = "mail.server.com"
73 | server = smtplib.SMTP(host)
74 | subject = "Test email from Python"
75 | to = email
76 | from_addr = "test@pylib.com"
77 | body_text = "Here is the Alpha copy of Python 101, Part I"
78 |
79 | # create the message
80 | msg = MIMEMultipart()
81 | msg["From"] = from_addr
82 | msg["Subject"] = subject
83 | msg["Date"] = formatdate(localtime=True)
84 | msg["To"] = email
85 |
86 | msg.attach( MIMEText(body_text) )
87 |
88 | attachment = MIMEBase('application', "octet-stream")
89 | try:
90 | with open(pdf, "rb") as fh:
91 | data = fh.read()
92 | attachment.set_payload( data )
93 | encoders.encode_base64(attachment)
94 | attachment.add_header(*header)
95 | msg.attach(attachment)
96 | except IOError:
97 | msg = "Error opening attachment file %s" % file_to_attach
98 | print(msg)
99 |
100 | server.sendmail(from_addr, to, msg.as_string())
101 |
102 | def main(path):
103 | """"""
104 | try:
105 | with open(path) as csv_file:
106 | reader = csv.reader(csv_file)
107 | for line in reader:
108 | name, email = line
109 | pdf = make_book(name, email)
110 | send_email(email, pdf)
111 | except IOError:
112 | print("Error reading file: %s" % path)
113 | raise
114 |
115 | if __name__ == "__main__":
116 | main("backers.csv")
--------------------------------------------------------------------------------
/code/Appendix A/csv_reader.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | def read_csv(path):
4 | """"""
5 | try:
6 | with open(path) as csv_file:
7 | reader = csv.reader(csv_file)
8 | for line in reader:
9 | name, email = line
10 | print(name)
11 | print(email)
12 | except IOError:
13 | print("Error reading file: %s" % path)
14 | raise
15 |
16 | if __name__ == "__main__":
17 | path = "backers.csv"
18 | read_csv(path)
--------------------------------------------------------------------------------
/code/Appendix A/send_email.py:
--------------------------------------------------------------------------------
1 | import os
2 | import smtplib
3 |
4 | from email import encoders
5 | from email.mime.text import MIMEText
6 | from email.mime.base import MIMEBase
7 | from email.mime.multipart import MIMEMultipart
8 | from email.utils import formatdate
9 |
10 | def send_email(email, pdf):
11 | """
12 | Send an email out
13 | """
14 | header0 = 'Content-Disposition'
15 | header1 ='attachment; filename="%s"' % os.path.basename(pdf)
16 | header = header0, header1
17 |
18 | host = "mail.server.com"
19 | server = smtplib.SMTP(host)
20 | subject = "Test email from Python"
21 | to = email
22 | from_addr = "test@pylib.com"
23 | body_text = "Here is the Alpha copy of Python 101, Part I"
24 |
25 | # create the message
26 | msg = MIMEMultipart()
27 | msg["From"] = from_addr
28 | msg["Subject"] = subject
29 | msg["Date"] = formatdate(localtime=True)
30 | msg["To"] = email
31 |
32 | msg.attach( MIMEText(body_text) )
33 |
34 | attachment = MIMEBase('application', "octet-stream")
35 | try:
36 | with open(pdf, "rb") as fh:
37 | data = fh.read()
38 | attachment.set_payload( data )
39 | encoders.encode_base64(attachment)
40 | attachment.add_header(*header)
41 | msg.attach(attachment)
42 | except IOError:
43 | msg = "Error opening attachment file %s" % file_to_attach
44 | print(msg)
45 |
46 | server.sendmail(from_addr, to, msg.as_string())
47 |
48 | if __name__ == "__main__":
49 | send_email("mike@example.org", "output/python101.pdf")
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/add.py:
--------------------------------------------------------------------------------
1 | def add(a, b):
2 | return a + b
3 |
4 | # call the function with arguments
5 | add(1, 2)
6 |
7 | # call the function with the wrong number of arguments
8 | add(1) # causes a TypeError
9 |
10 | # call the function with keyword arguments
11 | add(a=2, b=3)
12 |
13 | # assign the result to a variable
14 | total = add(b=4, a=5)
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/args_and_kwargs.py:
--------------------------------------------------------------------------------
1 | def many(*args, **kwargs):
2 | print(args)
3 | print(kwargs)
4 |
5 | many(1, 2, 3, name="Mike", job="programmer")
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/kw_func.py:
--------------------------------------------------------------------------------
1 | # create a function with defaults
2 | def keyword_function(a=1, b=2):
3 | return a+b
4 |
5 | # call it with keyword arguments
6 | keyword_function(b=4, a=5)
7 |
8 | # call the function without arguments (i.e. use the defaults)
9 | keyword_function()
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/kw_func2.py:
--------------------------------------------------------------------------------
1 | def mixed_function(a, b=2, c=3):
2 | return a+b+c
3 |
4 | # call the function with one argument and 2 keyword arguments
5 | mixed_function(1, b=4, c=5)
6 |
7 | # call the argument with just the required argument
8 | mixed_function(1)
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/scope.py:
--------------------------------------------------------------------------------
1 | # this script demonstrates scope issues and will
2 | # raise a NameError if run
3 |
4 | def function_a():
5 | a = 1
6 | b = 2
7 | return a+b
8 |
9 | def function_b():
10 | c = 3
11 | return a+c
12 |
13 | print( function_a() )
14 | print( function_b() )
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/scope2.py:
--------------------------------------------------------------------------------
1 | # this script demonstrates how to use a global
2 | # to fic the scope issue in scope.py
3 |
4 | def function_a():
5 | global a
6 | a = 1
7 | b = 2
8 | return a+b
9 |
10 | def function_b():
11 | c = 3
12 | return a+c
13 |
14 | print(function_a())
15 | print(function_b())
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/simple_function.py:
--------------------------------------------------------------------------------
1 | # create a simple function
2 | def a_function():
3 | print("You just created a function!")
--------------------------------------------------------------------------------
/code/Chapter 10 - Functions/stub.py:
--------------------------------------------------------------------------------
1 | def empty_function():
2 | pass
--------------------------------------------------------------------------------
/code/Chapter 11 - Classes/car_subclass.py:
--------------------------------------------------------------------------------
1 | class Car(Vehicle):
2 | """
3 | The Car class
4 | """
5 |
6 |
7 | def brake(self):
8 | """
9 | Override brake method
10 | """
11 | return "The car class is breaking slowly!"
12 |
13 |
14 | if __name__ == "__main__":
15 | car = Car("yellow", 2, 4, "car")
16 | car.brake()
17 | 'The car class is breaking slowly!'
18 | car.drive()
19 | "I'm driving a yellow car!"
--------------------------------------------------------------------------------
/code/Chapter 11 - Classes/simple_class_2.x.py:
--------------------------------------------------------------------------------
1 | # Python 2.x syntax
2 | class Vehicle(object):
3 | """docstring"""
4 |
5 | def __init__(self):
6 | """Constructor"""
7 | pass
--------------------------------------------------------------------------------
/code/Chapter 11 - Classes/simple_class_3.x.py:
--------------------------------------------------------------------------------
1 | # Python 3.x syntax
2 | class Vehicle:
3 | """docstring"""
4 |
5 | def __init__(self):
6 | """Constructor"""
7 | pass
--------------------------------------------------------------------------------
/code/Chapter 11 - Classes/vehicle.py:
--------------------------------------------------------------------------------
1 | class Vehicle(object):
2 | """docstring"""
3 |
4 |
5 | def __init__(self, color, doors, tires):
6 | """Constructor"""
7 | self.color = color
8 | self.doors = doors
9 | self.tires = tires
10 |
11 |
12 | def brake(self):
13 | """
14 | Stop the car
15 | """
16 | return "Braking"
17 |
18 |
19 | def drive(self):
20 | """
21 | Drive the car
22 | """
23 | return "I'm driving!"
24 |
25 |
26 | if __name__ == "__main__":
27 | car = Vehicle("blue", 5, 4)
28 | print(car.color)
29 | truck = Vehicle("red", 3, 6)
30 | print(truck.color)
--------------------------------------------------------------------------------
/code/Chapter 11 - Classes/vehicle2.py:
--------------------------------------------------------------------------------
1 | class Vehicle(object):
2 | """docstring"""
3 |
4 |
5 | def __init__(self, color, doors, tires, vtype):
6 | """Constructor"""
7 | self.color = color
8 | self.doors = doors
9 | self.tires = tires
10 | self.vtype = vtype
11 |
12 |
13 | def brake(self):
14 | """
15 | Stop the car
16 | """
17 | return "%s braking" % self.vtype
18 |
19 |
20 | def drive(self):
21 | """
22 | Drive the car
23 | """
24 | return "I'm driving a %s %s!" % (self.color, self.vtype)
25 |
26 |
27 | if __name__ == "__main__":
28 | car = Vehicle("blue", 5, 4, "car")
29 | print(car.brake())
30 | print(car.drive())
31 | truck = Vehicle("red", 3, 6, "truck")
32 | print(truck.drive())
33 | print(truck.brake())
--------------------------------------------------------------------------------
/code/Chapter 12 - Introspection/readme.txt:
--------------------------------------------------------------------------------
1 | This chapter was skipped because it just demonstrates different ways of importing modules. The examples in chapter 12 should be practiced in IDLE or a Python editor of your choice.
--------------------------------------------------------------------------------
/code/Chapter 13 - csv/csv_dictwriter.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | def csv_dict_writer(path, fieldnames, data):
4 | """
5 | Writes a CSV file using DictWriter
6 | """
7 | with open(path, "w", newline='') as out_file:
8 | writer = csv.DictWriter(out_file, delimiter=',', fieldnames=fieldnames)
9 | writer.writeheader()
10 | for row in data:
11 | writer.writerow(row)
12 |
13 | if __name__ == "__main__":
14 | data = ["first_name,last_name,city".split(","),
15 | "Tyrese,Hirthe,Strackeport".split(","),
16 | "Jules,Dicki,Lake Nickolasville".split(","),
17 | "Dedric,Medhurst,Stiedemannberg".split(",")
18 | ]
19 | my_list = []
20 | fieldnames = data[0]
21 | for values in data[1:]:
22 | inner_dict = dict(zip(fieldnames, values))
23 | my_list.append(inner_dict)
24 |
25 | path = "dict_output.csv"
26 | csv_dict_writer(path, fieldnames, my_list)
--------------------------------------------------------------------------------
/code/Chapter 13 - csv/csv_reader.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | def csv_reader(file_obj):
4 | """
5 | Read a csv file
6 | """
7 | reader = csv.reader(file_obj)
8 | for row in reader:
9 | print(" ".join(row))
10 |
11 |
12 | if __name__ == "__main__":
13 | csv_path = "TB_data_dictionary_2014-02-26.csv"
14 | with open(csv_path, "r") as f_obj:
15 | csv_reader(f_obj)
--------------------------------------------------------------------------------
/code/Chapter 13 - csv/csv_reader2.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | def csv_dict_reader(file_obj):
4 | """
5 | Read a CSV file using csv.DictReader
6 | """
7 | reader = csv.DictReader(file_obj, delimiter=',')
8 | for line in reader:
9 | print(line["first_name"]),
10 | print(line["last_name"])
11 |
12 | if __name__ == "__main__":
13 | with open("data.csv") as f_obj:
14 | csv_dict_reader(f_obj)
--------------------------------------------------------------------------------
/code/Chapter 13 - csv/csv_writer.py:
--------------------------------------------------------------------------------
1 | import csv
2 |
3 | def csv_writer(data, path):
4 | """
5 | Write data to a CSV file path
6 | """
7 | with open(path, "w", newline='') as csv_file:
8 | writer = csv.writer(csv_file, delimiter=',')
9 | for line in data:
10 | writer.writerow(line)
11 |
12 | if __name__ == "__main__":
13 | data = ["first_name,last_name,city".split(","),
14 | "Tyrese,Hirthe,Strackeport".split(","),
15 | "Jules,Dicki,Lake Nickolasville".split(","),
16 | "Dedric,Medhurst,Stiedemannberg".split(",")
17 | ]
18 | path = "output.csv"
19 | csv_writer(data, path)
--------------------------------------------------------------------------------
/code/Chapter 13 - csv/data.csv:
--------------------------------------------------------------------------------
1 | first_name,last_name,address,city,state,zip_code
2 | Tyrese,Hirthe,1404 Turner Ville,Strackeport,NY,19106-8813
3 | Jules,Dicki,2410 Estella Cape Suite 061,Lake Nickolasville,ME,00621-7435
4 | Dedric,Medhurst,6912 Dayna Shoal,Stiedemannberg,SC,43259-2273
--------------------------------------------------------------------------------
/code/Chapter 14 - configparser/create_config.py:
--------------------------------------------------------------------------------
1 | import configparser
2 |
3 | def createConfig(path):
4 | """
5 | Create a config file
6 | """
7 | config = configparser.ConfigParser()
8 | config.add_section("Settings")
9 | config.set("Settings", "font", "Courier")
10 | config.set("Settings", "font_size", "10")
11 | config.set("Settings", "font_style", "Normal")
12 | config.set("Settings", "font_info",
13 | "You are using %(font)s at %(font_size)s pt")
14 |
15 | with open(path, "w") as config_file:
16 | config.write(config_file)
17 |
18 | if __name__ == "__main__":
19 | path = "settings.ini"
20 | createConfig(path)
--------------------------------------------------------------------------------
/code/Chapter 14 - configparser/crud_config.py:
--------------------------------------------------------------------------------
1 | import configparser
2 | import os
3 |
4 | from create_config import createConfig
5 |
6 |
7 | def crudConfig(path):
8 | """
9 | Create, read, update, delete config
10 | """
11 | if not os.path.exists(path):
12 | createConfig(path)
13 |
14 | stat = os.stat(path)
15 | if stat.st_size == 0:
16 | # File is zero bytes
17 | raise RuntimeError('Settings file is empty')
18 |
19 | config = configparser.ConfigParser()
20 | config.read(path)
21 |
22 | # read some values from the config
23 | font = config.get("Settings", "font")
24 | font_size = config.get("Settings", "font_size")
25 |
26 | # change a value in the config
27 | config.set("Settings", "font_size", "12")
28 |
29 | # delete a value from the config
30 | config.remove_option("Settings", "font_style")
31 |
32 | # write changes back to the config file
33 | with open(path, "w") as config_file:
34 | config.write(config_file)
35 |
36 | if __name__ == "__main__":
37 | path = "settings.ini"
38 | crudConfig(path)
--------------------------------------------------------------------------------
/code/Chapter 14 - configparser/crud_config_refactored.py:
--------------------------------------------------------------------------------
1 | import configparser
2 | import os
3 |
4 | def create_config(path):
5 | """
6 | Create a config file
7 | """
8 | config = configparser.ConfigParser()
9 | config.add_section("Settings")
10 | config.set("Settings", "font", "Courier")
11 | config.set("Settings", "font_size", "10")
12 | config.set("Settings", "font_style", "Normal")
13 | config.set("Settings", "font_info",
14 | "You are using %(font)s at %(font_size)s pt")
15 |
16 | with open(path, "w") as config_file:
17 | config.write(config_file)
18 |
19 |
20 | def get_config(path):
21 | """
22 | Returns the config object
23 | """
24 | if not os.path.exists(path):
25 | create_config(path)
26 |
27 | config = configparser.ConfigParser()
28 | config.read(path)
29 | return config
30 |
31 |
32 | def get_setting(path, section, setting):
33 | """
34 | Print out a setting
35 | """
36 | config = get_config(path)
37 | value = config.get(section, setting)
38 | msg = "{section} {setting} is {value}".format(
39 | section=section, setting=setting, value=value)
40 | print(msg)
41 | return value
42 |
43 |
44 | def update_setting(path, section, setting, value):
45 | """
46 | Update a setting
47 | """
48 | config = get_config(path)
49 | config.set(section, setting, value)
50 | with open(path, "w") as config_file:
51 | config.write(config_file)
52 |
53 |
54 | def delete_setting(path, section, setting):
55 | """
56 | Delete a setting
57 | """
58 | config = get_config(path)
59 | config.remove_option(section, setting)
60 | with open(path, "w") as config_file:
61 | config.write(config_file)
62 |
63 | if __name__ == "__main__":
64 | path = "settings.ini"
65 | font = get_setting(path, 'Settings', 'font')
66 | font_size = get_setting(path, 'Settings', 'font_size')
67 |
68 | update_setting(path, "Settings", "font_size", "12")
69 |
70 | delete_setting(path, "Settings", "font_style")
--------------------------------------------------------------------------------
/code/Chapter 14 - configparser/interpolation.py:
--------------------------------------------------------------------------------
1 | import configparser
2 | import os
3 |
4 | from create_config import createConfig
5 |
6 |
7 | def interpolationDemo(path):
8 | if not os.path.exists(path):
9 | createConfig(path)
10 |
11 | config = configparser.ConfigParser()
12 | config.read(path)
13 |
14 | print(config.get("Settings", "font_info"))
15 |
16 | print(config.get("Settings", "font_info",
17 | vars={"font": "Arial", "font_size": "100"}))
18 |
19 | if __name__ == "__main__":
20 | path = "settings.ini"
21 | interpolationDemo(path)
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/exception_logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logging.basicConfig(filename="sample.log", level=logging.INFO)
4 | log = logging.getLogger("ex")
5 |
6 | try:
7 | raise RuntimeError
8 | except RuntimeError:
9 | log.exception("Error!")
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/log_multiple_modules.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import otherMod
3 |
4 | def main():
5 | """
6 | The main entry point of the application
7 | """
8 | logging.basicConfig(filename="mySnake.log", level=logging.INFO)
9 | logging.info("Program started")
10 | result = otherMod.add(7, 8)
11 | logging.info("Done!")
12 |
13 | if __name__ == "__main__":
14 | main()
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/log_multiple_modules2.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import otherMod2
3 |
4 | def main():
5 | """
6 | The main entry point of the application
7 | """
8 | logger = logging.getLogger("exampleApp")
9 | logger.setLevel(logging.INFO)
10 |
11 | # create the logging file handler
12 | fh = logging.FileHandler("new_snake.log")
13 |
14 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
15 | fh.setFormatter(formatter)
16 |
17 | # add handler to logger object
18 | logger.addHandler(fh)
19 |
20 | logger.info("Program started")
21 | result = otherMod2.add(7, 8)
22 | logger.info("Done!")
23 |
24 | if __name__ == "__main__":
25 | main()
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/log_with_config.py:
--------------------------------------------------------------------------------
1 | # log_with_config.py
2 | import logging
3 | import logging.config
4 | import otherMod2
5 |
6 | def main():
7 | """
8 | Based on http://docs.python.org/howto/logging.html#configuring-logging
9 | """
10 | logging.config.fileConfig('logging.conf')
11 | logger = logging.getLogger("exampleApp")
12 |
13 | logger.info("Program started")
14 | result = otherMod2.add(7, 8)
15 | logger.info("Done!")
16 |
17 | if __name__ == "__main__":
18 | main()
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/log_with_config2.py:
--------------------------------------------------------------------------------
1 | # log_with_config2.py
2 | import logging
3 | import logging.config
4 | import otherMod2
5 |
6 | def main():
7 | """
8 | Based on http://docs.python.org/howto/logging.html#configuring-logging
9 | """
10 | dictLogConfig = {
11 | "version":1,
12 | "handlers":{
13 | "fileHandler":{
14 | "class":"logging.FileHandler",
15 | "formatter":"myFormatter",
16 | "filename":"config2.log"
17 | }
18 | },
19 | "loggers":{
20 | "exampleApp":{
21 | "handlers":["fileHandler"],
22 | "level":"INFO",
23 | }
24 | },
25 | "formatters":{
26 | "myFormatter":{
27 | "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
28 | }
29 | }
30 | }
31 |
32 | logging.config.dictConfig(dictLogConfig)
33 |
34 | logger = logging.getLogger("exampleApp")
35 |
36 | logger.info("Program started")
37 | result = otherMod2.add(7, 8)
38 | logger.info("Done!")
39 |
40 | if __name__ == "__main__":
41 | main()
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/logging.conf:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root,exampleApp
3 |
4 | [handlers]
5 | keys=fileHandler, consoleHandler
6 |
7 | [formatters]
8 | keys=myFormatter
9 |
10 | [logger_root]
11 | level=CRITICAL
12 | handlers=consoleHandler
13 |
14 | [logger_exampleApp]
15 | level=INFO
16 | handlers=fileHandler
17 | qualname=exampleApp
18 |
19 | [handler_consoleHandler]
20 | class=StreamHandler
21 | level=DEBUG
22 | formatter=myFormatter
23 | args=(sys.stdout,)
24 |
25 | [handler_fileHandler]
26 | class=FileHandler
27 | formatter=myFormatter
28 | args=("config.log",)
29 |
30 | [formatter_myFormatter]
31 | format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
32 | datefmt=
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/otherMod.py:
--------------------------------------------------------------------------------
1 | # otherMod.py
2 | import logging
3 |
4 | def add(x, y):
5 | """"""
6 | logging.info("added %s and %s to get %s" % (x, y, x+y))
7 | return x+y
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/otherMod2.py:
--------------------------------------------------------------------------------
1 | # otherMod2.py
2 | import logging
3 |
4 | module_logger = logging.getLogger("exampleApp.otherMod2")
5 |
6 | def add(x, y):
7 | """"""
8 | logger = logging.getLogger("exampleApp.otherMod2.add")
9 | logger.info("added %s and %s to get %s" % (x, y, x+y))
10 | return x+y
--------------------------------------------------------------------------------
/code/Chapter 15 - logging/simple_logger.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | # add filemode="w" to overwrite
4 | logging.basicConfig(filename="sample.log", level=logging.INFO)
5 |
6 | logging.debug("This is a debug message")
7 | logging.info("Informational message")
8 | logging.error("An error has happened!")
--------------------------------------------------------------------------------
/code/Chapter 16 - os/readme.txt:
--------------------------------------------------------------------------------
1 | This chapter was skipped because it just demonstrates different ways of importing modules. The examples in chapter 16 should be practiced in IDLE or a Python editor of your choice.
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/email.ini:
--------------------------------------------------------------------------------
1 | [smtp]
2 | server = some.server.com
3 | from_addr = python@mydomain.com
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/send_email.py:
--------------------------------------------------------------------------------
1 | import smtplib
2 |
3 | HOST = "mySMTP.server.com"
4 | SUBJECT = "Test email from Python"
5 | TO = "mike@someAddress.org"
6 | FROM = "python@mydomain.com"
7 | text = "Python 3.4 rules them all!"
8 |
9 | BODY = "\r\n".join((
10 | "From: %s" % FROM,
11 | "To: %s" % TO,
12 | "Subject: %s" % SUBJECT ,
13 | "",
14 | text
15 | ))
16 |
17 | server = smtplib.SMTP(HOST)
18 | server.sendmail(FROM, [TO], BODY)
19 | server.quit()
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/send_email_attachment.py:
--------------------------------------------------------------------------------
1 | import os
2 | import smtplib
3 | import sys
4 |
5 | from configparser import ConfigParser
6 | from email import encoders
7 | from email.mime.text import MIMEText
8 | from email.mime.base import MIMEBase
9 | from email.mime.multipart import MIMEMultipart
10 | from email.utils import formatdate
11 |
12 | #----------------------------------------------------------------------
13 | def send_email_with_attachment(subject, body_text, to_emails,
14 | cc_emails, bcc_emails, file_to_attach):
15 | """
16 | Send an email with an attachment
17 | """
18 | base_path = os.path.dirname(os.path.abspath(__file__))
19 | config_path = os.path.join(base_path, "email.ini")
20 | header = 'Content-Disposition', 'attachment; filename="%s"' % file_to_attach
21 |
22 | # get the config
23 | if os.path.exists(config_path):
24 | cfg = ConfigParser()
25 | cfg.read(config_path)
26 | else:
27 | print("Config not found! Exiting!")
28 | sys.exit(1)
29 |
30 | # extract server and from_addr from config
31 | host = cfg.get("smtp", "server")
32 | from_addr = cfg.get("smtp", "from_addr")
33 |
34 | # create the message
35 | msg = MIMEMultipart()
36 | msg["From"] = from_addr
37 | msg["Subject"] = subject
38 | msg["Date"] = formatdate(localtime=True)
39 | if body_text:
40 | msg.attach( MIMEText(body_text) )
41 |
42 | msg["To"] = ', '.join(to_emails)
43 | msg["cc"] = ', '.join(cc_emails)
44 |
45 | attachment = MIMEBase('application', "octet-stream")
46 | try:
47 | with open(file_to_attach, "rb") as fh:
48 | data = fh.read()
49 | attachment.set_payload( data )
50 | encoders.encode_base64(attachment)
51 | attachment.add_header(*header)
52 | msg.attach(attachment)
53 | except IOError:
54 | msg = "Error opening attachment file %s" % file_to_attach
55 | print(msg)
56 | sys.exit(1)
57 |
58 | emails = to_emails + cc_emails
59 |
60 | server = smtplib.SMTP(host)
61 | server.sendmail(from_addr, emails, msg.as_string())
62 | server.quit()
63 |
64 | if __name__ == "__main__":
65 | emails = ["mike@someAddress.org", "nedry@jp.net"]
66 | cc_emails = ["someone@gmail.com"]
67 | bcc_emails = ["anonymous@circe.org"]
68 |
69 | subject = "Test email with attachment from Python"
70 | body_text = "This email contains an attachment!"
71 | path = "/path/to/some/file"
72 | send_email_with_attachment(subject, body_text, emails,
73 | cc_emails, bcc_emails, path)
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/send_email_function.py:
--------------------------------------------------------------------------------
1 | import smtplib
2 |
3 | def send_email(host, subject, to_addr, from_addr, body_text):
4 | """
5 | Send an email
6 | """
7 | BODY = "\r\n".join((
8 | "From: %s" % from_addr,
9 | "To: %s" % to_addr,
10 | "Subject: %s" % subject ,
11 | "",
12 | body_text
13 | ))
14 | server = smtplib.SMTP(host)
15 | server.sendmail(from_addr, [to_addr], BODY)
16 | server.quit()
17 |
18 | if __name__ == "__main__":
19 | host = "mySMTP.server.com"
20 | subject = "Test email from Python"
21 | to_addr = "mike@someAddress.org"
22 | from_addr = "python@mydomain.com"
23 | body_text = "Python rules them all!"
24 | send_email(host, subject, to_addr, from_addr, body_text)
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/send_multiple_emails.py:
--------------------------------------------------------------------------------
1 | import os
2 | import smtplib
3 | import sys
4 |
5 | from configparser import ConfigParser
6 |
7 | def send_email(subject, body_text, emails):
8 | """
9 | Send an email
10 | """
11 | base_path = os.path.dirname(os.path.abspath(__file__))
12 | config_path = os.path.join(base_path, "email.ini")
13 |
14 | if os.path.exists(config_path):
15 | cfg = ConfigParser()
16 | cfg.read(config_path)
17 | else:
18 | print("Config not found! Exiting!")
19 | sys.exit(1)
20 |
21 | host = cfg.get("smtp", "server")
22 | from_addr = cfg.get("smtp", "from_addr")
23 |
24 | BODY = "\r\n".join((
25 | "From: %s" % from_addr,
26 | "To: %s" % ', '.join(emails),
27 | "Subject: %s" % subject ,
28 | "",
29 | body_text
30 | ))
31 | server = smtplib.SMTP(host)
32 | server.sendmail(from_addr, emails, BODY)
33 | server.quit()
34 |
35 | if __name__ == "__main__":
36 | emails = ["mike@someAddress.org", "someone@gmail.com"]
37 | subject = "Test email from Python"
38 | body_text = "Python rules them all!"
39 | send_email(subject, body_text, emails)
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/send_to_cc_bcc.py:
--------------------------------------------------------------------------------
1 | import os
2 | import smtplib
3 | import sys
4 |
5 | from configparser import ConfigParser
6 |
7 | def send_email(subject, body_text, to_emails, cc_emails, bcc_emails):
8 | """
9 | Send an email
10 | """
11 | base_path = os.path.dirname(os.path.abspath(__file__))
12 | config_path = os.path.join(base_path, "email.ini")
13 |
14 | if os.path.exists(config_path):
15 | cfg = ConfigParser()
16 | cfg.read(config_path)
17 | else:
18 | print("Config not found! Exiting!")
19 | sys.exit(1)
20 |
21 | host = cfg.get("smtp", "server")
22 | from_addr = cfg.get("smtp", "from_addr")
23 |
24 | BODY = "\r\n".join((
25 | "From: %s" % from_addr,
26 | "To: %s" % ', '.join(to_emails),
27 | "CC: %s" % ', '.join(cc_emails),
28 | "BCC: %s" % ', '.join(bcc_emails),
29 | "Subject: %s" % subject ,
30 | "",
31 | body_text
32 | ))
33 | emails = to_emails + cc_emails + bcc_emails
34 |
35 | server = smtplib.SMTP(host)
36 | server.sendmail(from_addr, emails, BODY)
37 | server.quit()
38 |
39 | if __name__ == "__main__":
40 | emails = ["mike@somewhere.org"]
41 | cc_emails = ["someone@gmail.com"]
42 | bcc_emails = ["schmuck@newtel.net"]
43 | subject = "Test email from Python"
44 | body_text = "Python rules them all!"
45 | send_email(subject, body_text, emails, cc_emails, bcc_emails)
--------------------------------------------------------------------------------
/code/Chapter 17 - smtplib and email/smtp_config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import smtplib
3 | import sys
4 |
5 | from configparser import ConfigParser
6 |
7 | def send_email(subject, to_addr, body_text):
8 | """
9 | Send an email
10 | """
11 | base_path = os.path.dirname(os.path.abspath(__file__))
12 | config_path = os.path.join(base_path, "email.ini")
13 |
14 | if os.path.exists(config_path):
15 | cfg = ConfigParser()
16 | cfg.read(config_path)
17 | else:
18 | print("Config not found! Exiting!")
19 | sys.exit(1)
20 |
21 | host = cfg.get("smtp", "server")
22 | from_addr = cfg.get("smtp", "from_addr")
23 | BODY = "\r\n".join((
24 | "From: %s" % from_addr,
25 | "To: %s" % to_addr,
26 | "Subject: %s" % subject ,
27 | "",
28 | body_text
29 | ))
30 | server = smtplib.SMTP(host)
31 | server.sendmail(from_addr, [to_addr], BODY)
32 | server.quit()
33 |
34 | if __name__ == "__main__":
35 | subject = "Test email from Python"
36 | to_addr = "mike@someAddress.org"
37 | body_text = "Python rules them all!"
38 | send_email(subject, to_addr, body_text)
--------------------------------------------------------------------------------
/code/Chapter 18 - sqlite/basic_queries.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("mydatabase.db")
4 | #conn.row_factory = sqlite3.Row
5 | cursor = conn.cursor()
6 |
7 | sql = "SELECT * FROM albums WHERE artist=?"
8 | cursor.execute(sql, [("Red")])
9 | print cursor.fetchall() # or use fetchone()
10 |
11 | print "\nHere's a listing of all the records in the table:\n"
12 | for row in cursor.execute("SELECT rowid, * FROM albums ORDER BY artist"):
13 | print row
14 |
15 | print "\nResults from a LIKE query:\n"
16 | sql = """
17 | SELECT * FROM albums
18 | WHERE title LIKE 'The%'"""
19 | cursor.execute(sql)
20 | print cursor.fetchall()
--------------------------------------------------------------------------------
/code/Chapter 18 - sqlite/create_database.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("mydatabase.db") # or use :memory: to put it in RAM
4 |
5 | cursor = conn.cursor()
6 |
7 | # create a table
8 | cursor.execute("""CREATE TABLE albums
9 | (title text, artist text, release_date text,
10 | publisher text, media_type text)
11 | """)
12 |
13 | # insert some data
14 | cursor.execute("""INSERT INTO albums
15 | VALUES ('Glow', 'Andy Hunter', '7/24/2012',
16 | 'Xplore Records', 'MP3')"""
17 | )
18 |
19 | # save data to database
20 | conn.commit()
21 |
22 | # insert multiple records using the more secure "?" method
23 | albums = [('Exodus', 'Andy Hunter', '7/9/2002', 'Sparrow Records', 'CD'),
24 | ('Until We Have Faces', 'Red', '2/1/2011', 'Essential Records', 'CD'),
25 | ('The End is Where We Begin', 'Thousand Foot Krutch', '4/17/2012', 'TFKmusic', 'CD'),
26 | ('The Good Life', 'Trip Lee', '4/10/2012', 'Reach Records', 'CD')]
27 | cursor.executemany("INSERT INTO albums VALUES (?,?,?,?,?)", albums)
28 | conn.commit()
--------------------------------------------------------------------------------
/code/Chapter 18 - sqlite/delete_record.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("mydatabase.db")
4 | cursor = conn.cursor()
5 |
6 | sql = """
7 | DELETE FROM albums
8 | WHERE artist = 'John Doe'
9 | """
10 | cursor.execute(sql)
11 | conn.commit()
--------------------------------------------------------------------------------
/code/Chapter 18 - sqlite/update_database.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("mydatabase.db")
4 | cursor = conn.cursor()
5 |
6 | sql = """
7 | UPDATE albums
8 | SET artist = 'John Doe'
9 | WHERE artist = 'Andy Hunter'
10 | """
11 |
12 | cursor.execute(sql)
13 | conn.commit()
--------------------------------------------------------------------------------
/code/Chapter 19 - subprocess/communicate_example.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 |
3 | args = ["ping", "www.yahoo.com"]
4 | process = subprocess.Popen(args, stdout=subprocess.PIPE)
5 |
6 | data = process.communicate()
7 | for line in data:
8 | print(line)
--------------------------------------------------------------------------------
/code/Chapter 19 - subprocess/readme.txt:
--------------------------------------------------------------------------------
1 | Most of the examples in this chapter should be run in IDLE so you can better understand the subprocess module
--------------------------------------------------------------------------------
/code/Chapter 2 - Strings/creating_strings.py:
--------------------------------------------------------------------------------
1 | # The following shows different methods of creating a string
2 | my_string = "Welcome to Python!"
3 | another_string = 'The bright red fox jumped the fence.'
4 | a_long_string = '''This is a
5 | multi-line string. It covers more than
6 | one line'''
7 |
8 | # this set of strings shows how to mix single and double-quotes
9 | my_string = "I'm a Python programmer!"
10 | otherString = 'The word "python" usually refers to a snake'
11 | tripleString = """Here's another way to embed "quotes" in a string"""
12 |
13 | # cast an integer to a string using Python's str() class
14 | my_number = 123
15 | my_string = str(my_number)
--------------------------------------------------------------------------------
/code/Chapter 2 - Strings/string_concatenation.py:
--------------------------------------------------------------------------------
1 | # the following demonstrates how to join two strings
2 | string_one = "My dog ate "
3 | string_two = "my homework!"
4 | string_three = string_one + string_two
--------------------------------------------------------------------------------
/code/Chapter 2 - Strings/string_methods.py:
--------------------------------------------------------------------------------
1 | # string methods
2 | my_string = "This is a string!"
3 | my_string.upper() # or print(my_string.upper())
4 | "This is a string!".upper()
5 |
6 | # get a list of string methods
7 | dir(my_string)
8 |
9 | # get help
10 | help(my_string.capitalize)
11 |
--------------------------------------------------------------------------------
/code/Chapter 2 - Strings/string_slicing.py:
--------------------------------------------------------------------------------
1 | # string slicing
2 | my_string = "I like Python!"
3 | my_string[0:1]
4 | my_string[:1]
5 | my_string[0:12]
6 | my_string[0:13]
7 | my_string[0:14]
8 | my_string[0:-5]
9 | my_string[:]
10 | my_string[2:]
11 |
12 | # string indexing
13 | print(my_string[0]) # prints the first character of the string
--------------------------------------------------------------------------------
/code/Chapter 2 - Strings/string_substitution.py:
--------------------------------------------------------------------------------
1 | # string substitution
2 |
3 | # the old way
4 | my_string = "I like %s" % "Python"
5 | my_string
6 |
7 | var = "cookies"
8 | newString = "I like %s" % var
9 | newString
10 |
11 |
12 | another_string = "I like %s and %s" % ("Python", var)
13 | another_string
14 |
15 | # this will cause a TypeError
16 | another_string = "I like %s and %s" % "Python"
17 |
18 | # string formatting
19 | my_string = "%i + %i = %i" % (1,2,3)
20 | my_string
21 |
22 | float_string = "%f" % (1.23)
23 | float_string
24 |
25 | float_string2 = "%.2f" % (1.23)
26 | float_string2
27 |
28 | float_string3 = "%.2f" % (1.237)
29 | float_string3
30 |
31 | # passing bad data raises a TypeError
32 | int_float_err = "%i + %f" % ("1", "2.00")
33 |
34 | # this is bad too
35 | int_float_err = "%i + %f" % (1, "2.00")
36 |
37 | # ---------------------------
38 | # new style of string substitution / formatting
39 | print("%(lang)s is fun!" % {"lang":"Python"})
40 | print("%(value)s %(value)s %(value)s !" % {"value":"SPAM"})
41 |
42 | # this one won't work!
43 | print("%(x)i + %(y)i = %(z)i" % {"x":1, "y":2})
44 |
45 | # this is a fix of the previous example
46 | print("%(x)i + %(y)i = %(z)i" % {"x":1, "y":2, "z":3})
47 |
48 | # messing with the order of substitution
49 | "Python is as simple as {0}, {1}, {2}".format("a", "b", "c")
50 | "Python is as simple as {1}, {0}, {2}".format("a", "b", "c")
51 |
52 | # creating the dict and then doing the substitution
53 | xy = {"x":0, "y":10}
54 | print("Graph a point at where x={x} and y={y}".format(**xy))
--------------------------------------------------------------------------------
/code/Chapter 20 - sys/call_exit.py:
--------------------------------------------------------------------------------
1 | # call_exit.py
2 | import subprocess
3 |
4 | code = subprocess.call(["python.exe", "exit.py"])
5 | print(code)
--------------------------------------------------------------------------------
/code/Chapter 20 - sys/exit.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | sys.exit(0)
--------------------------------------------------------------------------------
/code/Chapter 20 - sys/readme.txt:
--------------------------------------------------------------------------------
1 | Most of the examples in this chapter should be run in IDLE so you can better understand the sys module
--------------------------------------------------------------------------------
/code/Chapter 20 - sys/sysargv.py:
--------------------------------------------------------------------------------
1 | # sysargv.py
2 | import sys
3 |
4 | print(sys.argv)
--------------------------------------------------------------------------------
/code/Chapter 21 - threading/downloader_2x.py:
--------------------------------------------------------------------------------
1 | # Python 2 version
2 | import os
3 | import urllib2
4 |
5 | from threading import Thread
6 |
7 | class DownloadThread(Thread):
8 | """
9 | A threading example that can download a file
10 | """
11 |
12 | def __init__(self, url, name):
13 | """Initialize the thread"""
14 | Thread.__init__(self)
15 | self.name = name
16 | self.url = url
17 |
18 | def run(self):
19 | """Run the thread"""
20 | handle = urllib2.urlopen(self.url)
21 | fname = os.path.basename(self.url)
22 | with open(fname, "wb") as f_handler:
23 | while True:
24 | chunk = handle.read(1024)
25 | if not chunk:
26 | break
27 | f_handler.write(chunk)
28 | msg = "%s has finished downloading %s!" % (self.name,
29 | self.url)
30 | print(msg)
31 |
32 | def main(urls):
33 | """
34 | Run the program
35 | """
36 | for item, url in enumerate(urls):
37 | name = "Thread %s" % (item+1)
38 | thread = DownloadThread(url, name)
39 | thread.start()
40 |
41 | if __name__ == "__main__":
42 | urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
43 | "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
44 | "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
45 | "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
46 | "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]
47 | main(urls)
--------------------------------------------------------------------------------
/code/Chapter 21 - threading/downloader_3x.py:
--------------------------------------------------------------------------------
1 | # Python 3 version
2 | import os
3 | import urllib.request
4 |
5 | from threading import Thread
6 |
7 | class DownloadThread(Thread):
8 | """
9 | A threading example that can download a file
10 | """
11 |
12 | def __init__(self, url, name):
13 | """Initialize the thread"""
14 | Thread.__init__(self)
15 | self.name = name
16 | self.url = url
17 |
18 | def run(self):
19 | """Run the thread"""
20 | handle = urllib.request.urlopen(self.url)
21 | fname = os.path.basename(self.url)
22 | with open(fname, "wb") as f_handler:
23 | while True:
24 | chunk = handle.read(1024)
25 | if not chunk:
26 | break
27 | f_handler.write(chunk)
28 | msg = "%s has finished downloading %s!" % (self.name,
29 | self.url)
30 | print(msg)
31 |
32 | def main(urls):
33 | """
34 | Run the program
35 | """
36 | for item, url in enumerate(urls):
37 | name = "Thread %s" % (item+1)
38 | thread = DownloadThread(url, name)
39 | thread.start()
40 |
41 | if __name__ == "__main__":
42 | urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
43 | "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
44 | "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
45 | "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
46 | "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]
47 | main(urls)
--------------------------------------------------------------------------------
/code/Chapter 21 - threading/downloader_queues.py:
--------------------------------------------------------------------------------
1 | import os
2 | import threading
3 | import urllib.request
4 |
5 | from queue import Queue
6 |
7 | class Downloader(threading.Thread):
8 | """Threaded File Downloader"""
9 |
10 | def __init__(self, queue):
11 | """Initialize the thread"""
12 | threading.Thread.__init__(self)
13 | self.queue = queue
14 |
15 | def run(self):
16 | """Run the thread"""
17 | while True:
18 | # gets the url from the queue
19 | url = self.queue.get()
20 |
21 | # download the file
22 | self.download_file(url)
23 |
24 | # send a signal to the queue that the job is done
25 | self.queue.task_done()
26 |
27 | def download_file(self, url):
28 | """Download the file"""
29 | handle = urllib.request.urlopen(url)
30 | fname = os.path.basename(url)
31 | with open(fname, "wb") as f:
32 | while True:
33 | chunk = handle.read(1024)
34 | if not chunk: break
35 | f.write(chunk)
36 |
37 | def main(urls):
38 | """
39 | Run the program
40 | """
41 | queue = Queue()
42 |
43 | # create a thread pool and give them a queue
44 | for i in range(5):
45 | t = Downloader(queue)
46 | t.setDaemon(True)
47 | t.start()
48 |
49 | # give the queue some data
50 | for url in urls:
51 | queue.put(url)
52 |
53 | # wait for the queue to finish
54 | queue.join()
55 |
56 | if __name__ == "__main__":
57 | urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
58 | "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
59 | "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
60 | "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
61 | "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]
62 | main(urls)
--------------------------------------------------------------------------------
/code/Chapter 21 - threading/simple_threads.py:
--------------------------------------------------------------------------------
1 | import random
2 | import time
3 |
4 | from threading import Thread
5 |
6 | class MyThread(Thread):
7 | """
8 | A threading example
9 | """
10 | def __init__(self, name):
11 | """Initialize the thread"""
12 | Thread.__init__(self)
13 | self.name = name
14 |
15 | def run(self):
16 | """Run the thread"""
17 | amount = random.randint(3, 15)
18 | time.sleep(amount)
19 | msg = "%s is running" % self.name
20 | print(msg)
21 |
22 | def create_threads():
23 | """
24 | Create a group of threads
25 | """
26 | for i in range(5):
27 | name = "Thread #%s" % (i+1)
28 | my_thread = MyThread(name)
29 | my_thread.start()
30 |
31 | if __name__ == "__main__":
32 | create_threads()
--------------------------------------------------------------------------------
/code/Chapter 22 - time/readme.txt:
--------------------------------------------------------------------------------
1 | Most of the examples in this chapter should be run in IDLE so you can better understand the datetime and time modules
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/appt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1181251680
5 | 040000008200E000
6 | 1181572063
7 |
8 |
9 | 1800
10 | Bring pizza home
11 |
12 |
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/create_with_elementtree.py:
--------------------------------------------------------------------------------
1 | import xml.etree.ElementTree as xml
2 |
3 | def createXML(filename):
4 | """
5 | Create an example XML file
6 | """
7 | root = xml.Element("zAppointments")
8 | appt = xml.Element("appointment")
9 | root.append(appt)
10 |
11 | # add appointment children
12 | begin = xml.SubElement(appt, "begin")
13 | begin.text = "1181251680"
14 |
15 | uid = xml.SubElement(appt, "uid")
16 | uid.text = "040000008200E000"
17 |
18 | alarmTime = xml.SubElement(appt, "alarmTime")
19 | alarmTime.text = "1181572063"
20 |
21 | state = xml.SubElement(appt, "state")
22 |
23 | location = xml.SubElement(appt, "location")
24 |
25 | duration = xml.SubElement(appt, "duration")
26 | duration.text = "1800"
27 |
28 | subject = xml.SubElement(appt, "subject")
29 |
30 | tree = xml.ElementTree(root)
31 | tree.write(filename)
32 |
33 | if __name__ == "__main__":
34 | createXML("appt.xml")
35 |
36 |
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/edit_with_elementtree.py:
--------------------------------------------------------------------------------
1 | import time
2 | import xml.etree.cElementTree as ET
3 |
4 | def editXML(filename):
5 | """
6 | Edit an example XML file
7 | """
8 | tree = ET.ElementTree(file=filename)
9 | root = tree.getroot()
10 |
11 | for begin_time in root.iter("begin"):
12 | begin_time.text = time.ctime(int(begin_time.text))
13 |
14 | tree = ET.ElementTree(root)
15 | tree.write('updated.xml')
16 |
17 | if __name__ == "__main__":
18 | editXML("original_appt.xml")
19 |
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/example.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Gambardella, Matthew
5 | XML Developer's Guide
6 | Computer
7 | 44.95
8 | 2000-10-01
9 | An in-depth look at creating applications
10 | with XML.
11 |
12 |
13 | Ralls, Kim
14 | Midnight Rain
15 | Fantasy
16 | 5.95
17 | 2000-12-16
18 | A former architect battles corporate zombies,
19 | an evil sorceress, and her own childhood to become queen
20 | of the world.
21 |
22 |
23 | Corets, Eva
24 | Maeve Ascendant
25 | Fantasy
26 | 5.95
27 | 2000-11-17
28 | After the collapse of a nanotechnology
29 | society in England, the young survivors lay the
30 | foundation for a new society.
31 |
32 |
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/minidom_parse.py:
--------------------------------------------------------------------------------
1 | import xml.dom.minidom
2 | import urllib.request
3 |
4 | class ApptParser(object):
5 |
6 | def __init__(self, url, flag='url'):
7 | self.list = []
8 | self.appt_list = []
9 | self.flag = flag
10 | self.rem_value = 0
11 | xml = self.getXml(url)
12 | self.handleXml(xml)
13 |
14 | def getXml(self, url):
15 | try:
16 | print(url)
17 | f = urllib.request.urlopen(url)
18 | except:
19 | f = url
20 |
21 | doc = xml.dom.minidom.parse(f)
22 | node = doc.documentElement
23 | if node.nodeType == xml.dom.Node.ELEMENT_NODE:
24 | print('Element name: %s' % node.nodeName)
25 | for (name, value) in node.attributes.items():
26 | print(' Attr -- Name: %s Value: %s' % (name, value))
27 |
28 | return node
29 |
30 | def handleXml(self, xml):
31 | rem = xml.getElementsByTagName('zAppointments')
32 | appointments = xml.getElementsByTagName("appointment")
33 | self.handleAppts(appointments)
34 |
35 | def getElement(self, element):
36 | return self.getText(element.childNodes)
37 |
38 | def handleAppts(self, appts):
39 | for appt in appts:
40 | self.handleAppt(appt)
41 | self.list = []
42 |
43 | def handleAppt(self, appt):
44 | begin = self.getElement(appt.getElementsByTagName("begin")[0])
45 | duration = self.getElement(appt.getElementsByTagName("duration")[0])
46 | subject = self.getElement(appt.getElementsByTagName("subject")[0])
47 | location = self.getElement(appt.getElementsByTagName("location")[0])
48 | uid = self.getElement(appt.getElementsByTagName("uid")[0])
49 |
50 | self.list.append(begin)
51 | self.list.append(duration)
52 | self.list.append(subject)
53 | self.list.append(location)
54 | self.list.append(uid)
55 | if self.flag == 'file':
56 |
57 | try:
58 | state = self.getElement(appt.getElementsByTagName("state")[0])
59 | self.list.append(state)
60 | alarm = self.getElement(appt.getElementsByTagName("alarmTime")[0])
61 | self.list.append(alarm)
62 | except Exception as e:
63 | print(e)
64 |
65 | self.appt_list.append(self.list)
66 |
67 | def getText(self, nodelist):
68 | rc = ""
69 | for node in nodelist:
70 | if node.nodeType == node.TEXT_NODE:
71 | rc = rc + node.data
72 | return rc
73 |
74 | if __name__ == "__main__":
75 | appt = ApptParser("appt.xml")
76 | print(appt.appt_list)
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/minidom_parse2.py:
--------------------------------------------------------------------------------
1 | import xml.dom.minidom as minidom
2 |
3 | def getTitles(xml):
4 | """
5 | Print out all titles found in xml
6 | """
7 | doc = minidom.parse(xml)
8 | node = doc.documentElement
9 | books = doc.getElementsByTagName("book")
10 |
11 | titles = []
12 | for book in books:
13 | titleObj = book.getElementsByTagName("title")[0]
14 | titles.append(titleObj)
15 |
16 | for title in titles:
17 | nodes = title.childNodes
18 | for node in nodes:
19 | if node.nodeType == node.TEXT_NODE:
20 | print(node.data)
21 |
22 | if __name__ == "__main__":
23 | document = 'example.xml'
24 | getTitles(document)
25 |
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/original_appt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1181251680
5 | 040000008200E000
6 | 1181572063
7 |
8 |
9 | 1800
10 | Bring pizza home
11 |
12 |
13 | 1181253977
14 | sdlkjlkadhdakhdfd
15 | 1181588888
16 | TX
17 | Dallas
18 | 1800
19 | Bring pizza home
20 |
21 |
--------------------------------------------------------------------------------
/code/Chapter 23 - xml/parse_with_elementtree.py:
--------------------------------------------------------------------------------
1 | import xml.etree.cElementTree as ET
2 |
3 | def parseXML(xml_file):
4 | """
5 | Parse XML with ElementTree
6 | """
7 | tree = ET.ElementTree(file=xml_file)
8 | print(tree.getroot())
9 | root = tree.getroot()
10 | print("tag=%s, attrib=%s" % (root.tag, root.attrib))
11 |
12 | for child in root:
13 | print(child.tag, child.attrib)
14 | if child.tag == "appointment":
15 | for step_child in child:
16 | print(step_child.tag)
17 |
18 | # iterate over the entire tree
19 | print("-" * 40)
20 | print("Iterating using a tree iterator")
21 | print("-" * 40)
22 | iter_ = tree.getiterator()
23 | for elem in iter_:
24 | print(elem.tag)
25 |
26 | # get the information via the children!
27 | print("-" * 40)
28 | print("Iterating using getchildren()")
29 | print("-" * 40)
30 | appointments = root.getchildren()
31 | for appointment in appointments:
32 | appt_children = appointment.getchildren()
33 | for appt_child in appt_children:
34 | print("%s=%s" % (appt_child.tag, appt_child.text))
35 |
36 | if __name__ == "__main__":
37 | parseXML("appt.xml")
--------------------------------------------------------------------------------
/code/Chapter 24 - pdb/debug_test.py:
--------------------------------------------------------------------------------
1 | # debug_test.py
2 |
3 | def doubler(a):
4 | """"""
5 | result = a*2
6 | print(result)
7 | return result
8 |
9 | def main():
10 | """"""
11 | for i in range(1,10):
12 | doubler(i)
13 |
14 | if __name__ == "__main__":
15 | main()
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/add_property.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 | class Fees(object):
4 | """"""
5 |
6 | def __init__(self):
7 | """Constructor"""
8 | self._fee = None
9 |
10 | def get_fee(self):
11 | """
12 | Return the current fee
13 | """
14 | return self._fee
15 |
16 | def set_fee(self, value):
17 | """
18 | Set the fee
19 | """
20 | if isinstance(value, str):
21 | self._fee = Decimal(value)
22 | elif isinstance(value, Decimal):
23 | self._fee = value
24 |
25 | fee = property(get_fee, set_fee)
26 |
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/add_property_setter.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 | class Fees(object):
4 | """"""
5 |
6 | def __init__(self):
7 | """Constructor"""
8 | self._fee = None
9 |
10 | @property
11 | def fee(self):
12 | """
13 | The fee property - the getter
14 | """
15 | return self._fee
16 |
17 | @fee.setter
18 | def fee(self, value):
19 | """
20 | The setter of the fee property
21 | """
22 | if isinstance(value, str):
23 | self._fee = Decimal(value)
24 | elif isinstance(value, Decimal):
25 | self._fee = value
26 |
27 | if __name__ == "__main__":
28 | f = Fees()
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/builtin_decorators.py:
--------------------------------------------------------------------------------
1 | class DecoratorTest(object):
2 | """
3 | Test regular method vs @classmethod vs @staticmethod
4 | """
5 |
6 | def __init__(self):
7 | """Constructor"""
8 | pass
9 |
10 | def doubler(self, x):
11 | """"""
12 | print("running doubler")
13 | return x*2
14 |
15 | @classmethod
16 | def class_tripler(klass, x):
17 | """"""
18 | print("running tripler: %s" % klass)
19 | return x*3
20 |
21 | @staticmethod
22 | def static_quad(x):
23 | """"""
24 | print("running quad")
25 | return x*4
26 |
27 | if __name__ == "__main__":
28 | decor = DecoratorTest()
29 | print(decor.doubler(5))
30 | print(decor.class_tripler(3))
31 | print(DecoratorTest.class_tripler(3))
32 | print(DecoratorTest.static_quad(2))
33 | print(decor.static_quad(3))
34 | print(decor.doubler)
35 | print(decor.class_tripler)
36 | print(decor.static_quad)
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/logging_decorator.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | def log(func):
4 | """
5 | Log what function is called
6 | """
7 | def wrap_log(*args, **kwargs):
8 | name = func.__name__
9 | logger = logging.getLogger(name)
10 | logger.setLevel(logging.INFO)
11 |
12 | # add file handler
13 | fh = logging.FileHandler("%s.log" % name)
14 | fmt = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
15 | formatter = logging.Formatter(fmt)
16 | fh.setFormatter(formatter)
17 | logger.addHandler(fh)
18 |
19 | logger.info("Running function: %s" % name)
20 | result = func(*args, **kwargs)
21 | logger.info("Result: %s" % result)
22 | return func
23 | return wrap_log
24 |
25 | @log
26 | def double_function(a):
27 | """
28 | Double the input parameter
29 | """
30 | return a*2
31 |
32 | if __name__ == "__main__":
33 | value = double_function(2)
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/properties.py:
--------------------------------------------------------------------------------
1 | class Person(object):
2 | """"""
3 |
4 | def __init__(self, first_name, last_name):
5 | """Constructor"""
6 | self.first_name = first_name
7 | self.last_name = last_name
8 |
9 | @property
10 | def full_name(self):
11 | """
12 | Return the full name
13 | """
14 | return "%s %s" % (self.first_name, self.last_name)
15 |
16 | if __name__ == "__main__":
17 | person = Person("Mike", "Driscoll")
18 | print(person.full_name)
19 | print(person.first_name)
20 | person.first_name = "Dan"
21 | print(person.full_name)
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/property_setters_getters.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 |
3 | class Fees(object):
4 | """"""
5 |
6 | def __init__(self):
7 | """Constructor"""
8 | self._fee = None
9 |
10 | def get_fee(self):
11 | """
12 | Return the current fee
13 | """
14 | return self._fee
15 |
16 | def set_fee(self, value):
17 | """
18 | Set the fee
19 | """
20 | if isinstance(value, str):
21 | self._fee = Decimal(value)
22 | elif isinstance(value, Decimal):
23 | self._fee = value
24 |
25 | if __name__ == "__main__":
26 | f = Fees()
27 | f.set_fee("1")
28 | print( f.get_fee() )
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/simple_decorator.py:
--------------------------------------------------------------------------------
1 | def another_function(func):
2 | """
3 | A function that accepts another function
4 | """
5 |
6 | def other_func():
7 | val = "The result of %s is %s" % (func(),
8 | eval(func())
9 | )
10 | return val
11 | return other_func
12 |
13 | def a_function():
14 | """A pretty useless function"""
15 | return "1+1"
16 |
17 | if __name__ == "__main__":
18 | value = a_function()
19 | print(value)
20 | decorator = another_function(a_function)
21 | print(decorator())
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/simple_decorator2.py:
--------------------------------------------------------------------------------
1 | def another_function(func):
2 | """
3 | A function that accepts another function
4 | """
5 |
6 | def other_func():
7 | val = "The result of %s is %s" % (func(),
8 | eval(func())
9 | )
10 | return val
11 | return other_func
12 |
13 | @another_function
14 | def a_function():
15 | """A pretty useless function"""
16 | return "1+1"
17 |
18 | if __name__ == "__main__":
19 | value = a_function()
20 | print(value)
--------------------------------------------------------------------------------
/code/Chapter 25 - decorators/simple_function.py:
--------------------------------------------------------------------------------
1 | def a_function():
2 | """A pretty useless function"""
3 | return "1+1"
4 |
5 | if __name__ == "__main__":
6 | value = a_function()
7 | print(value)
--------------------------------------------------------------------------------
/code/Chapter 26 - lambda/simple_lambda.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | def sqroot(x):
4 | """
5 | Finds the square root of the number passed in
6 | """
7 | return math.sqrt(x)
8 |
9 | if __name__ == "__main__":
10 | square_rt = lambda x: math.sqrt(x)
11 | print( sqroot(49) )
--------------------------------------------------------------------------------
/code/Chapter 26 - lambda/tkinter_lambda.py:
--------------------------------------------------------------------------------
1 | import Tkinter as tk
2 |
3 | class App:
4 | """"""
5 |
6 | def __init__(self, parent):
7 | """Constructor"""
8 | frame = tk.Frame(parent)
9 | frame.pack()
10 |
11 | btn22 = tk.Button(frame, text="22", command=lambda: self.printNum(22))
12 | btn22.pack(side=tk.LEFT)
13 | btn44 = tk.Button(frame, text="44", command=lambda: self.printNum(44))
14 | btn44.pack(side=tk.LEFT)
15 | quitBtn = tk.Button(frame, text="QUIT", fg="red", command=frame.quit)
16 | quitBtn.pack(side=tk.LEFT)
17 |
18 | def printNum(self, num):
19 | """"""
20 | print("You pressed the %s button" % num)
21 |
22 | if __name__ == "__main__":
23 | root = tk.Tk()
24 | app = App(root)
25 | root.mainloop()
--------------------------------------------------------------------------------
/code/Chapter 27 - profiling/ptest.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | def fast():
4 | """"""
5 | print("I run fast!")
6 |
7 | def slow():
8 | """"""
9 | time.sleep(3)
10 | print("I run slow!")
11 |
12 | def medium():
13 | """"""
14 | time.sleep(0.5)
15 | print("I run a little slowly...")
16 |
17 | def main():
18 | """"""
19 | fast()
20 | slow()
21 | medium()
22 |
23 | if __name__ == '__main__':
24 | main()
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/dtest1.py:
--------------------------------------------------------------------------------
1 | # dtest1.py
2 |
3 | def double(a):
4 | """
5 | >>> double(4)
6 | 8
7 | >>> double(9)
8 | 18
9 | """
10 | return a*2
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/dtest2.py:
--------------------------------------------------------------------------------
1 | def double(a):
2 | """
3 | >>> double(4)
4 | 8
5 | >>> double(9)
6 | 18
7 | """
8 | return a*2
9 |
10 | if __name__ == "__main__":
11 | import doctest
12 | doctest.testmod(verbose=True)
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/first_test_bowling.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | class TestBowling(unittest.TestCase):
4 | """"""
5 | def test_all_ones(self):
6 | """Constructor"""
7 | game = Game()
8 | game.roll(11, 1)
9 | self.assertEqual(game.score, 11)
10 |
11 | class Game:
12 | """"""
13 |
14 | def __init__(self):
15 | """Constructor"""
16 | self.score = 0
17 |
18 | def roll(self, numOfRolls, pins):
19 | """"""
20 | for roll in numOfRolls:
21 | self.score += pins
22 |
23 | if __name__ == '__main__':
24 | unittest.main()
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/first_test_bowling2.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | class TestBowling(unittest.TestCase):
4 | """"""
5 | def test_all_ones(self):
6 | """Constructor"""
7 | game = Game()
8 | game.roll(11, 1)
9 | self.assertEqual(game.score, 11)
10 |
11 | class Game:
12 | """"""
13 |
14 | def __init__(self):
15 | """Constructor"""
16 | self.score = 0
17 |
18 | def roll(self, numOfRolls, pins):
19 | """"""
20 | for roll in range(numOfRolls):
21 | self.score += pins
22 |
23 | if __name__ == '__main__':
24 | unittest.main()
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/game_v2.py:
--------------------------------------------------------------------------------
1 | # game_v2.py
2 |
3 | class Game:
4 | """"""
5 | def __init__(self):
6 | """Constructor"""
7 | self.score = 0
8 | self.pins = [0 for i in range(11)]
9 |
10 | def roll(self, numOfRolls, pins):
11 | """"""
12 | x = 0
13 | for pin in pins:
14 | self.pins[x] = pin
15 | x += 1
16 | x = 0
17 | spare_begin = 0
18 | spare_end = 2
19 | for roll in range(numOfRolls):
20 | spare = sum(self.pins[spare_begin:spare_end])
21 | if self.pins[x] == 10:
22 | self.score = self.pins[x] + self.pins[x+1] + self.pins[x+2]
23 | elif spare == 10:
24 | self.score = spare + self.pins[x+2]
25 | x += 1
26 | else:
27 | self.score += self.pins[x]
28 | x += 1
29 | if x == 11:
30 | break
31 | spare_begin += 2
32 | spare_end += 2
33 | print(self.score)
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/second_test_bowling.py:
--------------------------------------------------------------------------------
1 | from game import Game
2 | import unittest
3 |
4 | class TestBowling(unittest.TestCase):
5 | """"""
6 |
7 | def test_all_ones(self):
8 | """Constructor"""
9 | game = Game()
10 | pins = [1 for i in range(11)]
11 |
12 | game.roll(11, pins)
13 | self.assertEqual(game.score, 11)
14 |
15 | def test_strike(self):
16 | """
17 | A strike is 10 + the value of the next two rolls. So in this case
18 | the first frame will be 10+5+4 or 19 and the second will be
19 | 5+4. The total score would be 19+9 or 28.
20 | """
21 | game = Game()
22 | game.roll(11, [10, 5, 4])
23 | self.assertEqual(game.score, 28)
24 |
25 | if __name__ == '__main__':
26 | unittest.main()
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/second_test_bowling2.py:
--------------------------------------------------------------------------------
1 | from game import Game
2 | import unittest
3 |
4 | class TestBowling(unittest.TestCase):
5 | """"""
6 |
7 | def test_all_ones(self):
8 | """Constructor"""
9 | game = Game()
10 | pins = [1 for i in range(11)]
11 |
12 | game.roll(11, pins)
13 | self.assertEqual(game.score, 11)
14 |
15 | def test_strike(self):
16 | """
17 | A strike is 10 + the value of the next two rolls. So in this case
18 | the first frame will be 10+5+4 or 19 and the second will be
19 | 5+4. The total score would be 19+9 or 28.
20 | """
21 | game = Game()
22 | game.roll(11, [10, 5, 4])
23 | self.assertEqual(game.score, 28)
24 |
25 | class Game:
26 | """"""
27 |
28 | def __init__(self):
29 | """Constructor"""
30 | self.score = 0
31 | self.pins = [0 for i in range(11)]
32 |
33 | def roll(self, numOfRolls, pins):
34 | """"""
35 | x = 0
36 | for pin in pins:
37 | self.pins[x] = pin
38 | x += 1
39 | x = 0
40 | for roll in range(numOfRolls):
41 | if self.pins[x] == 10:
42 | self.score = self.pins[x] + self.pins[x+1] + self.pins[x+2]
43 | else:
44 | self.score += self.pins[x]
45 | x += 1
46 | print(self.score)
47 |
48 | if __name__ == '__main__':
49 | unittest.main()
--------------------------------------------------------------------------------
/code/Chapter 28 - testing/third_test_bowling.py:
--------------------------------------------------------------------------------
1 | from game_v2 import Game
2 | import unittest
3 |
4 | class TestBowling(unittest.TestCase):
5 | """"""
6 |
7 | def setUp(self):
8 | """"""
9 | self.game = Game()
10 |
11 | def test_all_ones(self):
12 | """
13 | If you don't get a strike or a spare, then you just add up the
14 | face value of the frame. In this case, each frame is worth
15 | one point, so the total is eleven.
16 | """
17 | pins = [1 for i in range(11)]
18 | self.game.roll(11, pins)
19 | self.assertEqual(self.game.score, 11)
20 |
21 | def test_spare(self):
22 | """
23 | A spare is worth 10, plus the value of your next roll. So in this
24 | case, the first frame will be 5+5+5 or 15 and the second will be
25 | 5+4 or 9. The total is 15+9, which equals 24,
26 | """
27 | self.game.roll(11, [5, 5, 5, 4])
28 | self.assertEqual(self.game.score, 24)
29 |
30 | def test_strike(self):
31 | """
32 | A strike is 10 + the value of the next two rolls. So in this case
33 | the first frame will be 10+5+4 or 19 and the second will be
34 | 5+4. The total score would be 19+9 or 28.
35 | """
36 | self.game.roll(11, [10, 5, 4])
37 | self.assertEqual(self.game.score, 28)
38 |
39 | if __name__ == '__main__':
40 | unittest.main()
--------------------------------------------------------------------------------
/code/Chapter 29 - installing modules/readme.txt:
--------------------------------------------------------------------------------
1 | The exercises in this chapter do not have corresponding code examples and are meant to be done via your console or terminal.
--------------------------------------------------------------------------------
/code/Chapter 3 - Lists Dicts Tuples/dict_examples.py:
--------------------------------------------------------------------------------
1 | # there are two ways to create a Python dictionary (dict)
2 | my_dict = {}
3 | another_dict = dict()
4 |
5 | # here's an example with the dict containing data
6 | my_other_dict = {"one":1, "two":2, "three":3}
7 |
8 | # access values in a dict
9 | my_other_dict["one"]
10 | my_dict = {"name":"Mike", "address":"123 Happy Way"}
11 | my_dict["name"]
12 |
13 | # check if a dict has a particular key
14 | "name" in my_dict # returns True
15 | "state" in my_dict # returns False
16 |
17 | # get a view of the keys in a dict
18 | my_dict.keys()
--------------------------------------------------------------------------------
/code/Chapter 3 - Lists Dicts Tuples/list_examples.py:
--------------------------------------------------------------------------------
1 | # two ways to create an empty list
2 | my_list = []
3 | my_list = list()
4 |
5 | # examples of lists
6 | my_list = [1, 2, 3]
7 | my_list2 = ["a", "b", "c"]
8 | my_list3 = ["a", 1, "Python", 5]
9 |
10 | # create a nested list
11 | my_nested_list = [my_list, my_list2]
12 |
13 | # combine / extend a list
14 | combo_list = []
15 | one_list = [4, 5]
16 | combo_list.extend(one_list)
17 |
18 | # or just concatenate the lists together
19 | my_list = [1, 2, 3]
20 | my_list2 = ["a", "b", "c"]
21 | combo_list = my_list + my_list2
22 |
23 | # sort a list
24 | alpha_list = [34, 23, 67, 100, 88, 2]
25 | alpha_list.sort()
26 | alpha_list
27 |
28 | # finding a logic error
29 | alpha_list = [34, 23, 67, 100, 88, 2]
30 | sorted_list = alpha_list.sort()
31 | # the sort method returns a None object as lists sort in-place
32 | print(sorted_list)
--------------------------------------------------------------------------------
/code/Chapter 3 - Lists Dicts Tuples/tuple_examples.py:
--------------------------------------------------------------------------------
1 | # a few tuple examples
2 | my_tuple = (1, 2, 3, 4, 5)
3 | my_tuple[0:3] # tuple slicing
4 | another_tuple = tuple() # creating an empty tuple
5 |
6 | # turn a list into a tuple via casting
7 | abc = tuple([1, 2, 3])
--------------------------------------------------------------------------------
/code/Chapter 30 - configobj/config.ini:
--------------------------------------------------------------------------------
1 | product = Sony PS3
2 | accessories = controller, eye, memory stick
3 | # This is a comment that will be ignored
4 | retail_price = $400
--------------------------------------------------------------------------------
/code/Chapter 30 - configobj/configobj_example.py:
--------------------------------------------------------------------------------
1 | import configobj
2 |
3 | def createConfig(path):
4 | config = configobj.ConfigObj()
5 | config.filename = path
6 | config["Sony"] = {}
7 | config["Sony"]["product"] = "Sony PS3"
8 | config["Sony"]["accessories"] = ['controller', 'eye', 'memory stick']
9 | config["Sony"]["retail price"] = "$400"
10 | config.write()
11 |
12 | if __name__ == "__main__":
13 | createConfig("config.ini")
--------------------------------------------------------------------------------
/code/Chapter 30 - configobj/configspec_example.py:
--------------------------------------------------------------------------------
1 | import configobj, validate
2 |
3 | cfg = """
4 | bmp_select_transparent = boolean(default=False)
5 | canvas_border = integer(min=10, max=35, default=15)
6 | colour1 = list(min=3, max=3, default=list('280', '0', '0'))
7 | colour2 = list(min=3, max=3, default=list('255', '255', '0'))
8 | colour3 = list(min=3, max=3, default=list('0', '255', '0'))
9 | colour4 = list(min=3, max=3, default=list('255', '0', '0'))
10 | colour5 = list(min=3, max=3, default=list('0', '0', '255'))
11 | colour6 = list(min=3, max=3, default=list('160', '32', '240'))
12 | colour7 = list(min=3, max=3, default=list('0', '255', '255'))
13 | colour8 = list(min=3, max=3, default=list('255', '165', '0'))
14 | colour9 = list(min=3, max=3, default=list('211', '211', '211'))
15 | convert_quality = option('highest', 'high', 'normal', default='normal')
16 | default_font = string
17 | default_width = integer(min=1, max=12000, default=640)
18 | default_height = integer(min=1, max=12000, default=480)
19 | imagemagick_path = string
20 | handle_size = integer(min=3, max=15, default=6)
21 | language = option('English', 'English (United Kingdom)', 'Russian', 'Hindi', default='English')
22 | print_title = boolean(default=True)
23 | statusbar = boolean(default=True)
24 | toolbar = boolean(default=True)
25 | toolbox = option('icon', 'text', default='icon')
26 | undo_sheets = integer(min=5, max=50, default=10)
27 | """
28 |
29 | def createConfig(path):
30 | """
31 | Create a config file using a configspec
32 | and validate it against a Validator object
33 | """
34 | spec = cfg.split("\n")
35 | config = configobj.ConfigObj(path, configspec=spec)
36 | validator = validate.Validator()
37 | config.validate(validator, copy=True)
38 | config.filename = path
39 | config.write()
40 |
41 | if __name__ == "__main__":
42 | createConfig("config.ini")
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/create_xml_with_objectify.py:
--------------------------------------------------------------------------------
1 | from lxml import etree, objectify
2 |
3 | def create_appt(data):
4 | """
5 | Create an appointment XML element
6 | """
7 | appt = objectify.Element("appointment")
8 | appt.begin = data["begin"]
9 | appt.uid = data["uid"]
10 | appt.alarmTime = data["alarmTime"]
11 | appt.state = data["state"]
12 | appt.location = data["location"]
13 | appt.duration = data["duration"]
14 | appt.subject = data["subject"]
15 | return appt
16 |
17 | def create_xml():
18 | """
19 | Create an XML file
20 | """
21 | xml = '''
22 |
23 |
24 | '''
25 |
26 | root = objectify.fromstring(xml)
27 | root.set("reminder", "15")
28 |
29 | appt = create_appt({"begin":1181251680,
30 | "uid":"040000008200E000",
31 | "alarmTime":1181572063,
32 | "state":"",
33 | "location":"",
34 | "duration":1800,
35 | "subject":"Bring pizza home"}
36 | )
37 | root.append(appt)
38 |
39 | uid = "604f4792-eb89-478b-a14f-dd34d3cc6c21-1234360800"
40 | appt = create_appt({"begin":1234360800,
41 | "uid":uid,
42 | "alarmTime":1181572063,
43 | "state":"dismissed",
44 | "location":"",
45 | "duration":1800,
46 | "subject":"Check MS Office website for updates"}
47 | )
48 | root.append(appt)
49 |
50 | # remove lxml annotation
51 | objectify.deannotate(root)
52 | etree.cleanup_namespaces(root)
53 |
54 | # create the xml string
55 | obj_xml = etree.tostring(root,
56 | pretty_print=True,
57 | xml_declaration=True)
58 | try:
59 | with open("example.xml", "wb") as xml_writer:
60 | xml_writer.write(obj_xml)
61 | except IOError:
62 | pass
63 |
64 | if __name__ == "__main__":
65 | create_xml()
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/example.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1181251680
5 | 040000008200E000
6 | 1181572063
7 |
8 |
9 | 1800
10 | Bring pizza home
11 |
12 |
13 | 1181253977
14 | sdlkjlkadhdakhdfd
15 | 1181588888
16 | TX
17 | Dallas
18 | 1800
19 | Bring pizza home
20 |
21 |
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/example2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Gambardella, Matthew
5 | XML Developer's Guide
6 | Computer
7 | 44.95
8 | 2000-10-01
9 | An in-depth look at creating applications
10 | with XML.
11 |
12 |
13 | Ralls, Kim
14 | Midnight Rain
15 | Fantasy
16 | 5.95
17 | 2000-12-16
18 | A former architect battles corporate zombies,
19 | an evil sorceress, and her own childhood to become queen
20 | of the world.
21 |
22 |
23 | Corets, Eva
24 | Maeve Ascendant
25 | Fantasy
26 | 5.95
27 | 2000-11-17
28 | After the collapse of a nanotechnology
29 | society in England, the young survivors lay the
30 | foundation for a new society.
31 |
32 |
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/parse_book_example.py:
--------------------------------------------------------------------------------
1 | from lxml import etree
2 | from StringIO import StringIO
3 |
4 | def parseBookXML(xmlFile):
5 |
6 | f = open(xmlFile)
7 | xml = f.read()
8 | f.close()
9 |
10 | tree = etree.parse(StringIO(xml))
11 | print(tree.docinfo.doctype)
12 | context = etree.iterparse(StringIO(xml))
13 | book_dict = {}
14 | books = []
15 | for action, elem in context:
16 | if not elem.text:
17 | text = "None"
18 | else:
19 | text = elem.text
20 | print(elem.tag + " => " + text)
21 | book_dict[elem.tag] = text
22 | if elem.tag == "book":
23 | books.append(book_dict)
24 | book_dict = {}
25 | return books
26 |
27 | if __name__ == "__main__":
28 | parseBookXML("example2.xml")
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/parse_book_example_refactored.py:
--------------------------------------------------------------------------------
1 | from lxml import etree
2 |
3 | def parseBookXML(xmlFile):
4 | """"""
5 | context = etree.iterparse(xmlFile)
6 | book_dict = {}
7 | books = []
8 | for action, elem in context:
9 | if not elem.text:
10 | text = "None"
11 | else:
12 | text = elem.text
13 | print(elem.tag + " => " + text)
14 | book_dict[elem.tag] = text
15 | if elem.tag == "book":
16 | books.append(book_dict)
17 | book_dict = {}
18 | return books
19 |
20 | if __name__ == "__main__":
21 | parseBookXML("example3.xml")
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/parse_with_objectify.py:
--------------------------------------------------------------------------------
1 | from lxml import etree, objectify
2 |
3 | def parseXML(xmlFile):
4 | """Parse the XML file"""
5 | with open(xmlFile) as f:
6 | xml = f.read()
7 |
8 | root = objectify.fromstring(xml)
9 |
10 | # returns attributes in element node as dict
11 | attrib = root.attrib
12 |
13 | # how to extract element data
14 | begin = root.appointment.begin
15 | uid = root.appointment.uid
16 |
17 | # loop over elements and print their tags and text
18 | for e in root.appointment.iterchildren():
19 | print("%s => %s" % (e.tag, e.text))
20 |
21 | # how to change an element's text
22 | root.appointment.begin = "something else"
23 | print(root.appointment.begin)
24 |
25 | # how to add a new element
26 | root.appointment.new_element = "new data"
27 |
28 | # remove the py:pytype stuff
29 | objectify.deannotate(root)
30 | etree.cleanup_namespaces(root)
31 | obj_xml = etree.tostring(root, pretty_print=True)
32 | print(obj_xml)
33 |
34 | # save your xml
35 | with open("new.xml", "w") as f:
36 | f.write(obj_xml)
37 |
38 | if __name__ == "__main__":
39 | f = r'path\to\sample.xml'
40 | parseXML(f)
--------------------------------------------------------------------------------
/code/Chapter 31 - lxml/simple_parser.py:
--------------------------------------------------------------------------------
1 | from lxml import etree
2 | from StringIO import StringIO
3 |
4 | def parseXML(xmlFile):
5 | """
6 | Parse the xml
7 | """
8 | f = open(xmlFile)
9 | xml = f.read()
10 | f.close()
11 |
12 | tree = etree.parse(StringIO(xml))
13 | context = etree.iterparse(StringIO(xml))
14 | for action, elem in context:
15 | if not elem.text:
16 | text = "None"
17 | else:
18 | text = elem.text
19 | print(elem.tag + " => " + text)
20 |
21 | if __name__ == "__main__":
22 | parseXML("example.xml")
--------------------------------------------------------------------------------
/code/Chapter 32 - code analysis/crummy_code.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | class CarClass:
4 | """"""
5 |
6 | def __init__(self, color, make, model, year):
7 | """Constructor"""
8 | self.color = color
9 | self.make = make
10 | self.model = model
11 | self.year = year
12 |
13 | if "Windows" in platform.platform():
14 | print("You're using Windows!")
15 |
16 | self.weight = self.getWeight(1, 2, 3)
17 |
18 | def getWeight(this):
19 | """"""
20 | return "2000 lbs"
--------------------------------------------------------------------------------
/code/Chapter 32 - code analysis/crummy_code_fixed.py:
--------------------------------------------------------------------------------
1 | # crummy_code_fixed.py
2 | import platform
3 |
4 | class CarClass:
5 | """"""
6 | def __init__(self, color, make, model, year):
7 | """Constructor"""
8 | self.color = color
9 | self.make = make
10 | self.model = model
11 | self.year = year
12 |
13 | if "Windows" in platform.platform():
14 | print("You're using Windows!")
15 |
16 | self.weight = self.get_weight(3)
17 |
18 | def get_weight(self, this):
19 | """"""
20 | return "2000 lbs"
--------------------------------------------------------------------------------
/code/Chapter 33 - requests/submit_form_requests.py:
--------------------------------------------------------------------------------
1 | import requests
2 |
3 | url = 'https://duckduckgo.com/html/'
4 | payload = {'q':'python'}
5 | r = requests.get(url, params=payload)
6 | with open("requests_results.html", "wb") as f:
7 | f.write(r.content)
--------------------------------------------------------------------------------
/code/Chapter 33 - requests/submit_form_urllib.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import urllib.parse
3 | import webbrowser
4 |
5 | data = urllib.parse.urlencode({'q': 'Python'})
6 | url = 'http://duckduckgo.com/html/'
7 | full_url = url + '?' + data
8 | response = urllib.request.urlopen(full_url)
9 | with open("results.html", "wb") as f:
10 | f.write(response.read())
11 |
12 | webbrowser.open("results.html")
--------------------------------------------------------------------------------
/code/Chapter 34 - SQLAlchemy/add_data.py:
--------------------------------------------------------------------------------
1 | # add_data.py
2 | import datetime
3 | from sqlalchemy import create_engine
4 | from sqlalchemy.orm import sessionmaker
5 | from table_def import Album, Artist
6 |
7 | engine = create_engine('sqlite:///mymusic.db', echo=True)
8 |
9 | # create a Session
10 | Session = sessionmaker(bind=engine)
11 | session = Session()
12 |
13 | # Create an artist
14 | new_artist = Artist(name="Newsboys")
15 | new_artist.albums = [Album(title="Read All About It",
16 | release_date=datetime.date(1988,12,1),
17 | publisher="Refuge", media_type="CD")]
18 |
19 | # add more albums
20 | more_albums = [Album(title="Hell Is for Wimps",
21 | release_date=datetime.date(1990,7,31),
22 | publisher="Star Song", media_type="CD"),
23 | Album(title="Love Liberty Disco",
24 | release_date=datetime.date(1999,11,16),
25 | publisher="Sparrow", media_type="CD"),
26 | Album(title="Thrive",
27 | release_date=datetime.date(2002,3,26),
28 | publisher="Sparrow", media_type="CD")]
29 | new_artist.albums.extend(more_albums)
30 |
31 | # Add the record to the session object
32 | session.add(new_artist)
33 |
34 | # commit the record the database
35 | session.commit()
36 |
37 | # Add several artists
38 | session.add_all([
39 | Artist(name="MXPX"),
40 | Artist(name="Kutless"),
41 | Artist(name="Thousand Foot Krutch")
42 | ])
43 | session.commit()
--------------------------------------------------------------------------------
/code/Chapter 34 - SQLAlchemy/deleting_data.py:
--------------------------------------------------------------------------------
1 | # deleting_data.py
2 | from sqlalchemy import create_engine
3 | from sqlalchemy.orm import sessionmaker
4 | from table_def import Album, Artist
5 |
6 | engine = create_engine('sqlite:///mymusic.db', echo=True)
7 |
8 | # create a Session
9 | Session = sessionmaker(bind=engine)
10 | session = Session()
11 |
12 | res = session.query(Artist).filter(Artist.name=="MXPX").first()
13 |
14 | session.delete(res)
15 | session.commit()
--------------------------------------------------------------------------------
/code/Chapter 34 - SQLAlchemy/modify_data.py:
--------------------------------------------------------------------------------
1 | # modify_data.py
2 | from sqlalchemy import create_engine
3 | from sqlalchemy.orm import sessionmaker
4 | from table_def import Album, Artist
5 |
6 | engine = create_engine('sqlite:///mymusic.db', echo=True)
7 |
8 | # create a Session
9 | Session = sessionmaker(bind=engine)
10 | session = Session()
11 |
12 | # querying for a record in the Artist table
13 | res = session.query(Artist).filter(Artist.name=="Kutless").first()
14 | print(res.name)
15 |
16 | # changing the name
17 | res.name = "Beach Boys"
18 | session.commit()
19 |
20 | # editing Album data
21 | artist, album = session.query(Artist, Album).filter(
22 | Artist.id==Album.artist_id).filter(Album.title=="Thrive").first()
23 | album.title = "Step Up to the Microphone"
24 | session.commit()
--------------------------------------------------------------------------------
/code/Chapter 34 - SQLAlchemy/queries.py:
--------------------------------------------------------------------------------
1 | # queries.py
2 | from sqlalchemy import create_engine
3 | from sqlalchemy.orm import sessionmaker
4 | from table_def import Album, Artist
5 |
6 | engine = create_engine('sqlite:///mymusic.db', echo=True)
7 |
8 | # create a Session
9 | Session = sessionmaker(bind=engine)
10 | session = Session()
11 |
12 | # how to do a SELECT * (i.e. all)
13 | res = session.query(Artist).all()
14 | for artist in res:
15 | print(artist.name)
16 |
17 | # how to SELECT the first result
18 | res = session.query(Artist).filter(Artist.name=="Newsboys").first()
19 |
20 | # how to sort the results (ORDER_BY)
21 | res = session.query(Album).order_by(Album.title).all()
22 | for album in res:
23 | print(album.title)
24 |
25 | # how to do a JOINed query
26 | qry = session.query(Artist, Album)
27 | qry = qry.filter(Artist.id==Album.artist_id)
28 | artist, album = qry.filter(Album.title=="Step Up to the Microphone").first()
29 |
30 | # how to use LIKE in a query
31 | res = session.query(Album).filter(Album.publisher.like("S%a%")).all()
32 | for item in res:
33 | print(item.publisher)
--------------------------------------------------------------------------------
/code/Chapter 34 - SQLAlchemy/table_def.py:
--------------------------------------------------------------------------------
1 | # table_def.py
2 | from sqlalchemy import create_engine, ForeignKey
3 | from sqlalchemy import Column, Date, Integer, String
4 | from sqlalchemy.ext.declarative import declarative_base
5 | from sqlalchemy.orm import relationship, backref
6 |
7 | engine = create_engine('sqlite:///mymusic.db', echo=True)
8 | Base = declarative_base()
9 |
10 | class Artist(Base):
11 | """"""
12 | __tablename__ = "artists"
13 |
14 | id = Column(Integer, primary_key=True)
15 | name = Column(String)
16 |
17 | class Album(Base):
18 | """"""
19 | __tablename__ = "albums"
20 |
21 | id = Column(Integer, primary_key=True)
22 | title = Column(String)
23 | release_date = Column(Date)
24 | publisher = Column(String)
25 | media_type = Column(String)
26 |
27 | artist_id = Column(Integer, ForeignKey("artists.id"))
28 | artist = relationship("Artist", backref=backref("albums", order_by=id))
29 |
30 | # create tables
31 | Base.metadata.create_all(engine)
--------------------------------------------------------------------------------
/code/Chapter 35 - virtualenv/readme.txt:
--------------------------------------------------------------------------------
1 | This chapter is meant to be done in a terminal or console.
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/arithmetic.py:
--------------------------------------------------------------------------------
1 | def add(x, y):
2 | return x + y
3 |
4 | def division(x, y):
5 | return x / y
6 |
7 | def multiply(x, y):
8 | return x * y
9 |
10 | def subtract(x, y):
11 | return x - y
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/arithmetic2.py:
--------------------------------------------------------------------------------
1 | def add(x, y):
2 | return x + y
3 |
4 | def division(x, y):
5 | return x / y
6 |
7 | def multiply(x, y):
8 | return x * y
9 |
10 | def subtract(x, y):
11 | return x - y
12 |
13 | if __name__ == "__main__":
14 | import sys
15 | print(sys.argv)
16 | v = sys.argv[1].lower()
17 | valOne = int(sys.argv[2])
18 | valTwo = int(sys.argv[3])
19 | if v == "a":
20 | print(add(valOne, valTwo))
21 | elif v == "d":
22 | print(division(valOne, valTwo))
23 | elif v == "m":
24 | print(multiply(valOne, valTwo))
25 | elif v == "s":
26 | print(subtract(valOne, valTwo))
27 | else:
28 | pass
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/modify_path.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | # modify this path to match your environment
4 | sys.path.append('C:\Users\mdriscoll\Documents')
5 |
6 | import mymath
7 |
8 | print(mymath.add(4,5))
9 | print(mymath.division(4, 2))
10 | print(mymath.multiply(10, 5))
11 | print(mymath.squareroot(48))
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/__init__.py:
--------------------------------------------------------------------------------
1 | # outer __init__.py
2 | from . add import add
3 | from . divide import division
4 | from . multiply import multiply
5 | from . subtract import subtract
6 | from .adv.sqrt import squareroot
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/add.py:
--------------------------------------------------------------------------------
1 | def add(x, y):
2 | return x + y
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/adv/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/code/Chapter 36 - creating modules and packages/mymath/adv/__init__.py
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/adv/sqrt.py:
--------------------------------------------------------------------------------
1 | # sqrt.py
2 | import math
3 |
4 | def squareroot(n):
5 | return math.sqrt(n)
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/divide.py:
--------------------------------------------------------------------------------
1 | def division(x, y):
2 | return x / y
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/multiply.py:
--------------------------------------------------------------------------------
1 | def multiply(x, y):
2 | return x * y
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/mymath/subtract.py:
--------------------------------------------------------------------------------
1 | def subtract(x, y):
2 | return x - y
--------------------------------------------------------------------------------
/code/Chapter 36 - creating modules and packages/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from setuptools import setup
3 |
4 | # This setup is suitable for "python setup.py develop".
5 | setup(name='mymath',
6 | version='0.1',
7 | description='A silly math package',
8 | author='Mike Driscoll',
9 | author_email='mike@mymath.org',
10 | url='http://www.mymath.org/',
11 | packages=['mymath', 'mymath.adv'],
12 | )
--------------------------------------------------------------------------------
/code/Chapter 37 - add your code to pypi/.pypirc:
--------------------------------------------------------------------------------
1 | [distutils]
2 | index-servers=
3 | pypi
4 | test
5 |
6 | [test]
7 | repository = https://testpypi.python.org/pypi
8 | username = richard
9 | password =
10 |
11 | [pypi]
12 | repository = http://pypi.python.org/pypi
13 | username = richard
14 | password =
--------------------------------------------------------------------------------
/code/Chapter 37 - add your code to pypi/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 |
3 | setup(name='mymath',
4 | version='0.1',
5 | packages=['mymath', 'mymath.adv'],
6 | )
--------------------------------------------------------------------------------
/code/Chapter 37 - add your code to pypi/setup2.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 |
3 | setup(name='mymath',
4 | version='0.1',
5 | description='A silly math package',
6 | author='Mike Driscoll',
7 | author_email='mike@mymath.org',
8 | url='http://www.mymath.org/',
9 | packages=['mymath', 'mymath.adv'],
10 | )
--------------------------------------------------------------------------------
/code/Chapter 38 - Python eggs/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 |
3 | setup(
4 | name = "mymath",
5 | version = "0.1",
6 | packages = find_packages()
7 | )
--------------------------------------------------------------------------------
/code/Chapter 39 - Python wheels/readme.txt:
--------------------------------------------------------------------------------
1 | This chapter is meant to be done in a terminal or console.
--------------------------------------------------------------------------------
/code/Chapter 4 - Conditionals/conditionals.py:
--------------------------------------------------------------------------------
1 | # a simple if statement
2 | if 2 > 1:
3 | print("This is a True statement!")
4 |
5 | # another simple if statement
6 | var1 = 1
7 | var2 = 3
8 | if var1 > var2:
9 | print("This is also True")
--------------------------------------------------------------------------------
/code/Chapter 40 - py2exe/advanced_setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 | import py2exe
3 |
4 | includes = []
5 | excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
6 | 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
7 | 'Tkconstants', 'Tkinter']
8 | packages = []
9 | dll_excludes = ['libgdk-win32-2.0-0.dll', 'libgobject-2.0-0.dll', 'tcl84.dll',
10 | 'tk84.dll']
11 |
12 | setup(
13 | options = {"py2exe": {"compressed": 2,
14 | "optimize": 2,
15 | "includes": includes,
16 | "excludes": excludes,
17 | "packages": packages,
18 | "dll_excludes": dll_excludes,
19 | "bundle_files": 3,
20 | "dist_dir": "dist",
21 | "xref": False,
22 | "skip_archive": False,
23 | "ascii": False,
24 | "custom_boot_script": '',
25 | }
26 | },
27 | windows=['sampleApp.py']
28 | )
--------------------------------------------------------------------------------
/code/Chapter 40 - py2exe/sampleApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | class DemoPanel(wx.Panel):
4 | """"""
5 | def __init__(self, parent):
6 | """Constructor"""
7 | wx.Panel.__init__(self, parent)
8 |
9 | labels = ["Name", "Address", "City", "State", "Zip",
10 | "Phone", "Email", "Notes"]
11 |
12 | mainSizer = wx.BoxSizer(wx.VERTICAL)
13 | lbl = wx.StaticText(self, label="Please enter your information here:")
14 | lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
15 | mainSizer.Add(lbl, 0, wx.ALL, 5)
16 | for lbl in labels:
17 | sizer = self.buildControls(lbl)
18 | mainSizer.Add(sizer, 1, wx.EXPAND)
19 | self.SetSizer(mainSizer)
20 | mainSizer.Layout()
21 |
22 | def buildControls(self, label):
23 | """
24 | Put the widgets together
25 | """
26 | sizer = wx.BoxSizer(wx.HORIZONTAL)
27 | size = (80,40)
28 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
29 | lbl = wx.StaticText(self, label=label, size=size)
30 | lbl.SetFont(font)
31 | sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
32 | if label != "Notes":
33 | txt = wx.TextCtrl(self, name=label)
34 | else:
35 | txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
36 | sizer.Add(txt, 1, wx.ALL, 5)
37 | return sizer
38 |
39 | class DemoFrame(wx.Frame):
40 | """
41 | Frame that holds all other widgets
42 | """
43 |
44 | def __init__(self):
45 | """Constructor"""
46 | wx.Frame.__init__(self, None, wx.ID_ANY,
47 | "Py2Exe Tutorial",
48 | size=(600,400)
49 | )
50 | panel = DemoPanel(self)
51 | self.Show()
52 |
53 | if __name__ == "__main__":
54 | app = wx.App(False)
55 | frame = DemoFrame()
56 | app.MainLoop()
--------------------------------------------------------------------------------
/code/Chapter 40 - py2exe/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 | import py2exe
3 |
4 | setup(windows=['sampleApp.py'])
--------------------------------------------------------------------------------
/code/Chapter 41 - bbfreeze/bb_setup.py:
--------------------------------------------------------------------------------
1 | # bb_setup.py
2 | from bbfreeze import Freezer
3 |
4 | f = Freezer(distdir="bb-binary")
5 | f.addScript("sampleApp.py")
6 | f()
--------------------------------------------------------------------------------
/code/Chapter 41 - bbfreeze/bb_setup2.py:
--------------------------------------------------------------------------------
1 | # bb_setup2.py
2 | from bbfreeze import Freezer
3 |
4 | includes = []
5 | excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
6 | 'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
7 | 'Tkconstants', 'Tkinter']
8 |
9 | bbFreeze_Class = Freezer('dist', includes=includes, excludes=excludes)
10 |
11 | bbFreeze_Class.addScript("sampleApp.py", gui_only=True)
12 |
13 | bbFreeze_Class.use_compression = 0
14 | bbFreeze_Class.include_py = True
15 | bbFreeze_Class()
--------------------------------------------------------------------------------
/code/Chapter 41 - bbfreeze/config_1.py:
--------------------------------------------------------------------------------
1 | # config_1.py
2 | import configobj
3 |
4 | def createConfig(configFile):
5 | """
6 | Create the configuration file
7 | """
8 | config = configobj.ConfigObj()
9 | inifile = configFile
10 | config.filename = inifile
11 | config['server'] = "http://www.google.com"
12 | config['username'] = "mike"
13 | config['password'] = "dingbat"
14 | config['update interval'] = 2
15 | config.write()
16 |
17 | def getConfig(configFile):
18 | """
19 | Open the config file and return a configobj
20 | """
21 | return configobj.ConfigObj(configFile)
22 |
23 | def createConfig2(path):
24 | """
25 | Create a config file
26 | """
27 | config = configobj.ConfigObj()
28 | config.filename = path
29 | config["Sony"] = {}
30 | config["Sony"]["product"] = "Sony PS3"
31 | config["Sony"]["accessories"] = ['controller', 'eye', 'memory stick']
32 | config["Sony"]["retail price"] = "$400"
33 | config.write()
34 |
35 | if __name__ == "__main__":
36 | createConfig2("sampleConfig2.ini")
--------------------------------------------------------------------------------
/code/Chapter 41 - bbfreeze/sampleApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | class DemoPanel(wx.Panel):
4 | """"""
5 | def __init__(self, parent):
6 | """Constructor"""
7 | wx.Panel.__init__(self, parent)
8 |
9 | labels = ["Name", "Address", "City", "State", "Zip",
10 | "Phone", "Email", "Notes"]
11 |
12 | mainSizer = wx.BoxSizer(wx.VERTICAL)
13 | lbl = wx.StaticText(self, label="Please enter your information here:")
14 | lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
15 | mainSizer.Add(lbl, 0, wx.ALL, 5)
16 | for lbl in labels:
17 | sizer = self.buildControls(lbl)
18 | mainSizer.Add(sizer, 1, wx.EXPAND)
19 | self.SetSizer(mainSizer)
20 | mainSizer.Layout()
21 |
22 | def buildControls(self, label):
23 | """
24 | Put the widgets together
25 | """
26 | sizer = wx.BoxSizer(wx.HORIZONTAL)
27 | size = (80,40)
28 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
29 | lbl = wx.StaticText(self, label=label, size=size)
30 | lbl.SetFont(font)
31 | sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
32 | if label != "Notes":
33 | txt = wx.TextCtrl(self, name=label)
34 | else:
35 | txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
36 | sizer.Add(txt, 1, wx.ALL, 5)
37 | return sizer
38 |
39 | class DemoFrame(wx.Frame):
40 | """
41 | Frame that holds all other widgets
42 | """
43 |
44 | def __init__(self):
45 | """Constructor"""
46 | wx.Frame.__init__(self, None, wx.ID_ANY,
47 | "Py2Exe Tutorial",
48 | size=(600,400)
49 | )
50 | panel = DemoPanel(self)
51 | self.Show()
52 |
53 | if __name__ == "__main__":
54 | app = wx.App(False)
55 | frame = DemoFrame()
56 | app.MainLoop()
--------------------------------------------------------------------------------
/code/Chapter 42 - cx_Freeze/config_1.py:
--------------------------------------------------------------------------------
1 | # config_1.py
2 | import configobj
3 |
4 | def createConfig(configFile):
5 | """
6 | Create the configuration file
7 | """
8 | config = configobj.ConfigObj()
9 | inifile = configFile
10 | config.filename = inifile
11 | config['server'] = "http://www.google.com"
12 | config['username'] = "mike"
13 | config['password'] = "dingbat"
14 | config['update interval'] = 2
15 | config.write()
16 |
17 | def getConfig(configFile):
18 | """
19 | Open the config file and return a configobj
20 | """
21 | return configobj.ConfigObj(configFile)
22 |
23 | def createConfig2(path):
24 | """
25 | Create a config file
26 | """
27 | config = configobj.ConfigObj()
28 | config.filename = path
29 | config["Sony"] = {}
30 | config["Sony"]["product"] = "Sony PS3"
31 | config["Sony"]["accessories"] = ['controller', 'eye', 'memory stick']
32 | config["Sony"]["retail price"] = "$400"
33 | config.write()
34 |
35 | if __name__ == "__main__":
36 | createConfig2("sampleConfig2.ini")
--------------------------------------------------------------------------------
/code/Chapter 42 - cx_Freeze/sampleApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | class DemoPanel(wx.Panel):
4 | """"""
5 | def __init__(self, parent):
6 | """Constructor"""
7 | wx.Panel.__init__(self, parent)
8 |
9 | labels = ["Name", "Address", "City", "State", "Zip",
10 | "Phone", "Email", "Notes"]
11 |
12 | mainSizer = wx.BoxSizer(wx.VERTICAL)
13 | lbl = wx.StaticText(self, label="Please enter your information here:")
14 | lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
15 | mainSizer.Add(lbl, 0, wx.ALL, 5)
16 | for lbl in labels:
17 | sizer = self.buildControls(lbl)
18 | mainSizer.Add(sizer, 1, wx.EXPAND)
19 | self.SetSizer(mainSizer)
20 | mainSizer.Layout()
21 |
22 | def buildControls(self, label):
23 | """
24 | Put the widgets together
25 | """
26 | sizer = wx.BoxSizer(wx.HORIZONTAL)
27 | size = (80,40)
28 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
29 | lbl = wx.StaticText(self, label=label, size=size)
30 | lbl.SetFont(font)
31 | sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
32 | if label != "Notes":
33 | txt = wx.TextCtrl(self, name=label)
34 | else:
35 | txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
36 | sizer.Add(txt, 1, wx.ALL, 5)
37 | return sizer
38 |
39 | class DemoFrame(wx.Frame):
40 | """
41 | Frame that holds all other widgets
42 | """
43 |
44 | def __init__(self):
45 | """Constructor"""
46 | wx.Frame.__init__(self, None, wx.ID_ANY,
47 | "Py2Exe Tutorial",
48 | size=(600,400)
49 | )
50 | panel = DemoPanel(self)
51 | self.Show()
52 |
53 | if __name__ == "__main__":
54 | app = wx.App(False)
55 | frame = DemoFrame()
56 | app.MainLoop()
--------------------------------------------------------------------------------
/code/Chapter 42 - cx_Freeze/setup.py:
--------------------------------------------------------------------------------
1 | # setup.py
2 | from cx_Freeze import setup, Executable
3 |
4 | setup(
5 | name = "wxSampleApp",
6 | version = "0.1",
7 | description = "An example wxPython script",
8 | executables = [Executable("sampleApp.py")]
9 | )
--------------------------------------------------------------------------------
/code/Chapter 42 - cx_Freeze/setup2.py:
--------------------------------------------------------------------------------
1 | from cx_Freeze import setup, Executable
2 |
3 | exe = Executable(
4 | script="sampleApp.py",
5 | base="Win32GUI",
6 | )
7 |
8 | setup(
9 | name = "wxSampleApp",
10 | version = "0.1",
11 | description = "An example wxPython script",
12 | executables = [exe]
13 | )
--------------------------------------------------------------------------------
/code/Chapter 43 - PyInstaller/config_1.py:
--------------------------------------------------------------------------------
1 | # config_1.py
2 | import configobj
3 |
4 | def createConfig(configFile):
5 | """
6 | Create the configuration file
7 | """
8 | config = configobj.ConfigObj()
9 | inifile = configFile
10 | config.filename = inifile
11 | config['server'] = "http://www.google.com"
12 | config['username'] = "mike"
13 | config['password'] = "dingbat"
14 | config['update interval'] = 2
15 | config.write()
16 |
17 | def getConfig(configFile):
18 | """
19 | Open the config file and return a configobj
20 | """
21 | return configobj.ConfigObj(configFile)
22 |
23 | def createConfig2(path):
24 | """
25 | Create a config file
26 | """
27 | config = configobj.ConfigObj()
28 | config.filename = path
29 | config["Sony"] = {}
30 | config["Sony"]["product"] = "Sony PS3"
31 | config["Sony"]["accessories"] = ['controller', 'eye', 'memory stick']
32 | config["Sony"]["retail price"] = "$400"
33 | config.write()
34 |
35 | if __name__ == "__main__":
36 | createConfig2("sampleConfig2.ini")
--------------------------------------------------------------------------------
/code/Chapter 43 - PyInstaller/sampleApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | class DemoPanel(wx.Panel):
4 | """"""
5 | def __init__(self, parent):
6 | """Constructor"""
7 | wx.Panel.__init__(self, parent)
8 |
9 | labels = ["Name", "Address", "City", "State", "Zip",
10 | "Phone", "Email", "Notes"]
11 |
12 | mainSizer = wx.BoxSizer(wx.VERTICAL)
13 | lbl = wx.StaticText(self, label="Please enter your information here:")
14 | lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
15 | mainSizer.Add(lbl, 0, wx.ALL, 5)
16 | for lbl in labels:
17 | sizer = self.buildControls(lbl)
18 | mainSizer.Add(sizer, 1, wx.EXPAND)
19 | self.SetSizer(mainSizer)
20 | mainSizer.Layout()
21 |
22 | def buildControls(self, label):
23 | """
24 | Put the widgets together
25 | """
26 | sizer = wx.BoxSizer(wx.HORIZONTAL)
27 | size = (80,40)
28 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
29 | lbl = wx.StaticText(self, label=label, size=size)
30 | lbl.SetFont(font)
31 | sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
32 | if label != "Notes":
33 | txt = wx.TextCtrl(self, name=label)
34 | else:
35 | txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
36 | sizer.Add(txt, 1, wx.ALL, 5)
37 | return sizer
38 |
39 | class DemoFrame(wx.Frame):
40 | """
41 | Frame that holds all other widgets
42 | """
43 |
44 | def __init__(self):
45 | """Constructor"""
46 | wx.Frame.__init__(self, None, wx.ID_ANY,
47 | "Py2Exe Tutorial",
48 | size=(600,400)
49 | )
50 | panel = DemoPanel(self)
51 | self.Show()
52 |
53 | if __name__ == "__main__":
54 | app = wx.App(False)
55 | frame = DemoFrame()
56 | app.MainLoop()
--------------------------------------------------------------------------------
/code/Chapter 44 - Creating an installer/sampleApp.py:
--------------------------------------------------------------------------------
1 | import wx
2 |
3 | class DemoPanel(wx.Panel):
4 | """"""
5 | def __init__(self, parent):
6 | """Constructor"""
7 | wx.Panel.__init__(self, parent)
8 |
9 | labels = ["Name", "Address", "City", "State", "Zip",
10 | "Phone", "Email", "Notes"]
11 |
12 | mainSizer = wx.BoxSizer(wx.VERTICAL)
13 | lbl = wx.StaticText(self, label="Please enter your information here:")
14 | lbl.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD))
15 | mainSizer.Add(lbl, 0, wx.ALL, 5)
16 | for lbl in labels:
17 | sizer = self.buildControls(lbl)
18 | mainSizer.Add(sizer, 1, wx.EXPAND)
19 | self.SetSizer(mainSizer)
20 | mainSizer.Layout()
21 |
22 | def buildControls(self, label):
23 | """
24 | Put the widgets together
25 | """
26 | sizer = wx.BoxSizer(wx.HORIZONTAL)
27 | size = (80,40)
28 | font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
29 | lbl = wx.StaticText(self, label=label, size=size)
30 | lbl.SetFont(font)
31 | sizer.Add(lbl, 0, wx.ALL|wx.CENTER, 5)
32 | if label != "Notes":
33 | txt = wx.TextCtrl(self, name=label)
34 | else:
35 | txt = wx.TextCtrl(self, style=wx.TE_MULTILINE, name=label)
36 | sizer.Add(txt, 1, wx.ALL, 5)
37 | return sizer
38 |
39 | class DemoFrame(wx.Frame):
40 | """
41 | Frame that holds all other widgets
42 | """
43 |
44 | def __init__(self):
45 | """Constructor"""
46 | wx.Frame.__init__(self, None, wx.ID_ANY,
47 | "Py2Exe Tutorial",
48 | size=(600,400)
49 | )
50 | panel = DemoPanel(self)
51 | self.Show()
52 |
53 | if __name__ == "__main__":
54 | app = wx.App(False)
55 | frame = DemoFrame()
56 | app.MainLoop()
--------------------------------------------------------------------------------
/code/Chapter 5 - Loops/for_loops.py:
--------------------------------------------------------------------------------
1 | # a basic for loop
2 | for number in range(5):
3 | print(number)
4 |
5 | # you can also write the above like this
6 | for number in [0, 1, 2, 3, 4]:
7 | print(number)
8 |
9 | # this is how to loop over the keys in a dict
10 | a_dict = {"one":1, "two":2, "three":3}
11 | for key in a_dict:
12 | print(key)
13 |
14 | # sort the keys before looping over them
15 | a_dict = {1:"one", 2:"two", 3:"three"}
16 | keys = a_dict.keys()
17 | sorted(keys)
18 | for key in keys:
19 | print(key)
20 |
21 | # Let's use a conditional to print out only even numbers
22 | for number in range(10):
23 | if number % 2 == 0:
24 | print(number)
25 |
26 | # using the else statement
27 | my_list = [1, 2, 3, 4, 5]
28 | for i in my_list:
29 | if i == 3:
30 | print("Item found!")
31 | break
32 | print(i)
33 | else:
34 | print("Item not found!")
--------------------------------------------------------------------------------
/code/Chapter 5 - Loops/while_loops.py:
--------------------------------------------------------------------------------
1 | # a simple while loop
2 | i = 0
3 | while i < 10:
4 | print(i)
5 | i = i + 1
6 |
7 | # this is how to break out of a loop
8 | while i < 10:
9 | print(i)
10 | if i == 5:
11 | break
12 | i += 1
13 |
14 | # an example of break and continue
15 | i = 0
16 | while i < 10:
17 | if i == 3:
18 | i += 1
19 | continue
20 |
21 | print(i)
22 |
23 | if i == 5:
24 | break
25 | i += 1
--------------------------------------------------------------------------------
/code/Chapter 6 - Comprehensions/comprehensions.py:
--------------------------------------------------------------------------------
1 | # a simple list comprehension
2 | x = [i for i in range(5)]
3 |
4 | # turn a list of strings into a list of ints
5 | x = ['1', '2', '3', '4', '5']
6 | y = [int(i) for i in x]
7 |
8 | # strip off all the leading or ending white space
9 | myStrings = [s.strip() for s in myStringList]
10 |
11 | # how to turn a list of lists into one list (flattening)
12 | vec = [[1,2,3], [4,5,6], [7,8,9]]
13 | flat_vec = [num for elem in vec for num in elem]
14 |
15 | # a simple dict comprehension
16 | print( {i: str(i) for i in range(5)} )
17 |
18 | # swapping keys and values with a dict comprehension
19 | my_dict = {1:"dog", 2:"cat", 3:"hamster"}
20 | print( {value:key for key, value in my_dict.items()} )
21 |
22 | # turn a list into a set using a set comprehension
23 | my_list = [1, 2, 2, 3, 4, 5, 5, 7, 8]
24 | my_set = {x for x in my_list}
--------------------------------------------------------------------------------
/code/Chapter 7 - Exceptions/exceptions.py:
--------------------------------------------------------------------------------
1 | # raise a ZeroDivisionError exception
2 | try:
3 | 1 / 0
4 | except ZeroDivisionError:
5 | print("You cannot divide by zero!")
6 |
7 | # this is known as a "bare except"
8 | try:
9 | 1 / 0
10 | except:
11 | print("You cannot divide by zero!")
12 |
13 | # let's raise a KeyError
14 | my_dict = {"a":1, "b":2, "c":3}
15 | try:
16 | value = my_dict["d"]
17 | except KeyError:
18 | print("That key does not exist!")
19 |
20 | # now let's raise an IndexError
21 | my_list = [1, 2, 3, 4, 5]
22 | try:
23 | my_list[6]
24 | except IndexError:
25 | print("That index is not in the list!")
26 |
27 | # the following shows how to catch multiple exceptions
28 | my_dict = {"a":1, "b":2, "c":3}
29 | try:
30 | value = my_dict["d"]
31 | except IndexError:
32 | print("This index does not exist!")
33 | except KeyError:
34 | print("This key is not in the dictionary!")
35 | except:
36 | print("Some other error occurred!")
37 |
38 | # here's a shorter method of catching multiple exceptions
39 | try:
40 | value = my_dict["d"]
41 | except (IndexError, KeyError):
42 | print("An IndexError or KeyError occurred!")
43 |
44 | # here is an example of the "finally" statement
45 | # note: the statement following finally always runs
46 | my_dict = {"a":1, "b":2, "c":3}
47 | try:
48 | value = my_dict["d"]
49 | except KeyError:
50 | print("A KeyError occurred!")
51 | finally:
52 | print("The finally statement has executed!")
53 |
54 | # here we learn how to use the "else" statement
55 | # note: else only runs when no errors occur
56 | my_dict = {"a":1, "b":2, "c":3}
57 | try:
58 | value = my_dict["a"]
59 | except KeyError:
60 | print("A KeyError occurred!")
61 | else:
62 | print("No error occurred!")
63 |
64 | # this last example demonstrates both else and finally
65 | my_dict = {"a":1, "b":2, "c":3}
66 | try:
67 | value = my_dict["a"]
68 | except KeyError:
69 | print("A KeyError occurred!")
70 | else:
71 | print("No error occurred!")
72 | finally:
73 | print("The finally statement ran!")
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/catching_errors.py:
--------------------------------------------------------------------------------
1 | # catching errors the old school way
2 | try:
3 | file_handler = open("test.txt")
4 | for line in file_handler:
5 | print(line)
6 | except IOError:
7 | print("An IOError has occurred!")
8 | finally:
9 | file_handler.close()
10 |
11 | # catching errors when using the with operator
12 | try:
13 | with open("test.txt") as file_handler:
14 | for line in file_handler:
15 | print(line)
16 | except IOError:
17 | print("An IOError has occurred!"
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/file_io.py:
--------------------------------------------------------------------------------
1 | # open a file that is in the same folder as this script
2 | handle = open("test.txt")
3 |
4 | # open a file by specifying its path
5 | handle = open(r"C:\Users\mike\py101book\data\test.txt", "r")
6 |
7 | # open the file in read-only binary mode
8 | handle = open("test.pdf", "rb")
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/open_and_close.py:
--------------------------------------------------------------------------------
1 | # open a file in read-only mode
2 | handle = open("test.txt", "r")
3 | # read the data
4 | data = handle.read()
5 | # print it out
6 | print(data)
7 | # close the file
8 | handle.close()
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/open_and_close2.py:
--------------------------------------------------------------------------------
1 | handle = open("test.txt", "r")
2 | data = handle.readline() # read just one line
3 | print(data)
4 | handle.close()
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/open_and_close3.py:
--------------------------------------------------------------------------------
1 | handle = open("test.txt", "r")
2 | data = handle.readlines() # read ALL the lines!
3 | print(data)
4 | handle.close()
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/open_with.py:
--------------------------------------------------------------------------------
1 | # open and read the file using the with operator
2 | with open("test.txt") as file_handler:
3 | for line in file_handler:
4 | print(line)
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/read_in_chunks.py:
--------------------------------------------------------------------------------
1 | handle = open("test.txt", "r")
2 | while True:
3 | data = handle.read(1024)
4 | print(data)
5 | if not data:
6 | break
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/read_line_by_line.py:
--------------------------------------------------------------------------------
1 | handle = open("test.txt", "r")
2 | for line in handle:
3 | print(line)
4 | handle.close()
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/test.txt:
--------------------------------------------------------------------------------
1 | This is a test file
2 | line 2
3 | line 3
4 | this line intentionally left blank
--------------------------------------------------------------------------------
/code/Chapter 8 - Working with Files/write_file.py:
--------------------------------------------------------------------------------
1 | handle = open("output.txt", "w")
2 | handle.write("This is a test!")
3 | handle.close()
--------------------------------------------------------------------------------
/code/Chapter 9 - Imports/readme.txt:
--------------------------------------------------------------------------------
1 | This chapter was skipped because it just demonstrates different ways of importing modules. The examples in chapter 9 should be practiced in IDLE or a Python editor of your choice.
--------------------------------------------------------------------------------
/manuscript/Book.txt:
--------------------------------------------------------------------------------
1 | intro.txt
2 | part_i.txt
3 | part_1_picture.txt
4 | chapter1.txt
5 | chapter2.txt
6 | chapter3.txt
7 | chapter4.txt
8 | chapter5.txt
9 | chapter6.txt
10 | chapter7.txt
11 | chapter8.txt
12 | chapter9.txt
13 | chapter10.txt
14 | chapter11.txt
15 | part_ii.txt
16 | part_2_picture.txt
17 | chapter12.txt
18 | chapter13.txt
19 | chapter14.txt
20 | chapter15.txt
21 | chapter16.txt
22 | chapter17.txt
23 | chapter18.txt
24 | chapter19.txt
25 | chapter20.txt
26 | chapter21.txt
27 | chapter22.txt
28 | chapter23.txt
29 | part_iii.txt
30 | part_3_picture.txt
31 | chapter24.txt
32 | chapter25.txt
33 | chapter26.txt
34 | chapter27.txt
35 | chapter28.txt
36 | part_iv.txt
37 | part_4_picture.txt
38 | chapter29.txt
39 | chapter30.txt
40 | chapter31.txt
41 | chapter32.txt
42 | chapter33.txt
43 | chapter34.txt
44 | chapter35.txt
45 | part_v.txt
46 | part_5_picture.txt
47 | chapter36.txt
48 | chapter37.txt
49 | chapter38.txt
50 | chapter39.txt
51 | chapter40.txt
52 | chapter41.txt
53 | chapter42.txt
54 | chapter43.txt
55 | chapter44.txt
56 | appendix_a.txt
--------------------------------------------------------------------------------
/manuscript/Sample.txt:
--------------------------------------------------------------------------------
1 | chapter1.txt
2 |
--------------------------------------------------------------------------------
/manuscript/chapter12.txt:
--------------------------------------------------------------------------------
1 | # Chapter 12 - Introspection
2 |
3 | Whether you're new to Python, been using it for a few years or you're an
4 | expert, knowing how to use Python's introspection capabilities can help
5 | your understanding of your code and that new package you just downloaded
6 | with the crappy documentation. Introspection is a fancy word that means
7 | to observe oneself and ponder one's thoughts, senses, and desires. In
8 | Python world, introspection is actually kind of similar. Introspection
9 | in this case is to use Python to figure out Python. In this chapter, you
10 | can learn how to use Python to give yourself a clue about the code
11 | you're working on or trying to learn. Some might even call it a form of
12 | debugging.
13 |
14 | Here's what we're going to cover:
15 |
16 | > - type
17 | > - dir
18 | > - help
19 |
20 | The Python Type
21 | ---------------
22 |
23 | You may not know this, but Python may just be your type. Yes, Python can
24 | tell you what type of variable you have or what type is returned from a
25 | function. It's a very handy little tool. Let's look at a few examples to
26 | make it all clear:
27 |
28 | ```python
29 | >>> x = "test"
30 | >>> y = 7
31 | >>> z = None
32 | >>> type(x)
33 |
34 | >>> type(y)
35 |
36 | >>> type(z)
37 |
38 | ```
39 |
40 | As you can see, Python has a keyword called **type** that can tell you
41 | what is what. In my real-life experiences, I've used **type** to help me
42 | figure out what is going on when my database data is corrupt or not what
43 | I expect. I just add a couple lines and print out each row's data along
44 | with its type. This has helped me a lot when I've been dumbfounded by
45 | some stupid code I wrote.
46 |
47 | The Python Dir
48 | --------------
49 |
50 | What is dir? Is it something you say when someone says or does something
51 | stupid? Not in this context! No, here on Planet Python, the dir keyword
52 | is used to tell the programmer what attributes and methods there are in
53 | the passed in object. If you forget to pass in an object, dir will
54 | return a list of names in the current scope. As usual, this is easier to
55 | understand with a few examples.
56 |
57 | ```python
58 | >>> dir("test")
59 | ['__add__', '__class__', '__contains__', '__delattr__',
60 | '__doc__', '__eq__', '__ge__', '__getattribute__',
61 | '__getitem__', '__getnewargs__', '__getslice__', '__gt__',
62 | '__hash__', '__init__', '__le__', '__len__', '__lt__',
63 | '__mod__', '__mul__', '__ne__', '__new__', '__reduce__',
64 | '__reduce_ex__', '__repr__', '__rmod__', '__rmul__',
65 | '__setattr__', '__str__', 'capitalize', 'center',
66 | 'count', 'decode', 'encode', 'endswith', 'expandtabs',
67 | 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower',
68 | 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower',
69 | 'lstrip', 'replace', 'rfind', 'rindex', 'rjust', 'rsplit',
70 | 'rstrip', 'split', 'splitlines', 'startswith', 'strip',
71 | 'swapcase', 'title', 'translate', 'upper', 'zfill']
72 | ```
73 |
74 | Since everything in Python is an object, we can pass a string to dir and
75 | find out what methods it has. Pretty neat, huh? Now let's try it with an
76 | imported module:
77 |
78 | ```python
79 | >>> import sys
80 | >>> dir(sys)
81 | ['__displayhook__', '__doc__', '__egginsert', '__excepthook__',
82 | '__name__', '__plen', '__stderr__', '__stdin__', '__stdout__',
83 | '_getframe', 'api_version', 'argv', 'builtin_module_names',
84 | 'byteorder', 'call_tracing', 'callstats', 'copyright',
85 | 'displayhook', 'dllhandle', 'exc_clear', 'exc_info',
86 | 'exc_traceback', 'exc_type', 'exc_value', 'excepthook',
87 | 'exec_prefix', 'executable', 'exit', 'exitfunc',
88 | 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding',
89 | 'getrecursionlimit', 'getrefcount', 'getwindowsversion', 'hexversion',
90 | 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
91 | 'path_importer_cache', 'platform', 'prefix', 'setcheckinterval',
92 | 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin',
93 | 'stdout', 'version', 'version_info', 'warnoptions', 'winver']
94 | ```
95 |
96 | Now, that's handy! If you haven't figured it out yet, the **dir**
97 | function is extremely handy for those 3rd party packages that you have
98 | downloaded (or will soon download) that have little to no documentation.
99 | How do you find out about what methods are available in these cases?
100 | Well, **dir** will help you figure it out. Of course, sometimes the
101 | documentation is in the code itself, which brings us to the builtin help
102 | utility.
103 |
104 | Python Help!
105 | ------------
106 |
107 | Python comes with a handy help utility. Just type "help()" (minus the
108 | quotes) into a Python shell and you'll see the following directions
109 | (Python version may vary)
110 |
111 | ```python
112 | >>> help()
113 |
114 | Welcome to Python 2.6! This is the online help utility.
115 |
116 | If this is your first time using Python, you should definitely check out
117 | the tutorial on the Internet at http://www.python.org/doc/tut/.
118 |
119 | Enter the name of any module, keyword, or topic to get help on writing
120 | Python programs and using Python modules. To quit this help utility and
121 | return to the interpreter, just type "quit".
122 |
123 | To get a list of available modules, keywords, or topics, type "modules",
124 | "keywords", or "topics". Each module also comes with a one-line summary
125 | of what it does; to list the modules whose summaries contain a given word
126 | such as "spam", type "modules spam".
127 |
128 | help>
129 | ```
130 |
131 | Note that you now have a "help>" prompt instead of the
132 | ">>>". When you are in help mode, you can explore the various
133 | modules, keywords and topics found in Python. Also note that when typing
134 | the word "modules", you will see a delay as Python searches its library
135 | folder to acquire a list. If you have installed a lot of 3rd party
136 | modules, this can take quite a while, so be prepared to go fix yourself
137 | a mocha while you wait. Once it's done, just follow the directions and
138 | play around with it and I think you'll get the gist.
139 |
140 | Wrapping Up
141 | -----------
142 |
143 | Now you know how to take an unknown module and learn a lot about it by
144 | just using some of Python's built-in functionality. You will find
145 | yourself using these commands over and over again to help you learn
146 | Python. As I mentioned earlier, you will find these tools especially
147 | helpful for the 3rd Party modules that don't believe in documentation.
148 |
--------------------------------------------------------------------------------
/manuscript/chapter24.txt:
--------------------------------------------------------------------------------
1 | # Chapter 24 - The Python Debugger
2 |
3 | Python comes with its own debugger module that is named **pdb**. This
4 | module provides an interactive source code debugger for your Python
5 | programs. You can set breakpoints, step through your code, inspect stack
6 | frames and more. We will look at the following aspects of the module:
7 |
8 | > - How to start the debugger
9 | > - Stepping through your code
10 | > - Setting breakpoints
11 |
12 | Let's start by creating a quick piece of code to attempt debugging with.
13 | Here's a silly example:
14 |
15 | ```python
16 | # debug_test.py
17 |
18 | def doubler(a):
19 | """"""
20 | result = a*2
21 | print(result)
22 | return result
23 |
24 | def main():
25 | """"""
26 | for i in range(1,10):
27 | doubler(i)
28 |
29 | if __name__ == "__main__":
30 | main()
31 | ```
32 |
33 | Now let's learn how to run the debugger against this piece of code.
34 |
35 | How to Start the Debugger
36 | -------------------------
37 |
38 | You can start the debugger three different ways. The first is to just
39 | import it and insert **pdb.set\_trace()** into your code to start the
40 | debugger. You can import the debugger in IDLE and have it run your
41 | module. Or you can call the debugger on the command line. We'll focus on
42 | the last two methods in this section. We will start with using it in the
43 | interpreter (IDLE). Open up a terminal (command line window) and
44 | navigate to where you save the above code example. Then start Python.
45 | Now do the following:
46 |
47 | ```python
48 | >>> import debug_test
49 | >>> import pdb
50 | >>> pdb.run('debug_test.main()')
51 | > (1)()
52 | (Pdb) continue
53 | 2
54 | 4
55 | 6
56 | 8
57 | 10
58 | 12
59 | 14
60 | 16
61 | 18
62 | >>>
63 | ```
64 |
65 | Here we import our module and pdb. Then we execute pdb's **run** method
66 | and tell it to call our module's **main** method. This brings up the
67 | debugger's prompt. Here we typed **continue** to tell it to go ahead and
68 | run the script. You can also type the letter **c** as a shortcut for
69 | continue. When you **continue**, the debugger will continue execution
70 | until it reaches a breakpoint or the script ends.
71 |
72 | The other way to start the debugger is to execute the following command
73 | via your terminal session:
74 |
75 | ```python
76 | python -m pdb debug_test.py
77 | ```
78 |
79 | If you run it this way, you will see a slightly different result:
80 |
81 | ```python
82 | -> def doubler(a):
83 | (Pdb) c
84 | 2
85 | 4
86 | 6
87 | 8
88 | 10
89 | 12
90 | 14
91 | 16
92 | 18
93 | The program finished and will be restarted
94 | ```
95 |
96 | You will note that in this example we used **c** instead of
97 | **continue**. You will also note that the debugger restarts at the end.
98 | This preserves the debugger's state (such as breakpoints) and can be
99 | more useful than having the debugger stop. Sometimes you'll need to go
100 | through the code several times to understand what's wrong with it.
101 |
102 | Let's dig a little deeper and learn how to step through the code.
103 |
104 | Stepping Through the Code
105 | -------------------------
106 |
107 | If you want to step through your code one line at a time, then you can
108 | use the **step** (or simply "s") command. Here's a session for your
109 | viewing pleasure:
110 |
111 | ```python
112 | C:\Users\mike>cd c:\py101
113 |
114 | c:\py101>python -m pdb debug_test.py
115 | > c:\py101\debug_test.py(4)()
116 | -> def doubler(a):
117 | (Pdb) step
118 | > c:\py101\debug_test.py(11)()
119 | -> def main():
120 | (Pdb) s
121 | > c:\py101\debug_test.py(16)()
122 | -> if __name__ == "__main__":
123 | (Pdb) s
124 | > c:\py101\debug_test.py(17)()
125 | -> main()
126 | (Pdb) s
127 | --Call--
128 | > c:\py101\debug_test.py(11)main()
129 | -> def main():
130 | (Pdb) next
131 | > c:\py101\debug_test.py(13)main()
132 | -> for i in range(1,10):
133 | (Pdb) s
134 | > c:\py101\debug_test.py(14)main()
135 | -> doubler(i)
136 | (Pdb)
137 | ```
138 |
139 | Here we start up the debugger and tell it to step into the code. It
140 | starts at the top and goes through the first two function definitions.
141 | Then it reaches the conditional and finds that it's supposed to execute
142 | the **main** function. We step into the main function and then use the
143 | **next** command. The **next** command will execute a called function if
144 | it encounters it without stepping into it. If you want to step into the
145 | called function, then you'll only want to just use the **step** command.
146 |
147 | When you see a line like **> c:py101debug\_test.py(13)main()**, you
148 | will want to pay attention to the number that's in the parentheses. This
149 | number is the current line number in the code.
150 |
151 | You can use the **args** (or **a**) to print the current argument list
152 | to the screen. Another handy command is **jump** (or **j**) followed by
153 | a space and the line number that you want to "jump" to. This gives you
154 | the ability to skip a bunch of monotonous stepping to get to the line
155 | that you want to get to. This leads us to learning about breakpoints!
156 |
157 | Setting breakpoints
158 | -------------------
159 |
160 | A breakpoint is a line in the code where you want to pause execution.
161 | You can set a breakpoint by calling the **break** (or **b**) command
162 | followed by a space and the line number that you want to break on. You
163 | can also prefix the line number with a filename and colon to specify a
164 | breakpoint in a different file. The break command also allows you to set
165 | a breakpoint with the **function** argument. There is also a **tbreak**
166 | command which will set a temporary breakpoint which is automatically
167 | removed when it gets hit.
168 |
169 | Here's an example:
170 |
171 | ```python
172 | c:\py101>python -m pdb debug_test.py
173 | > c:\py101\debug_test.py(4)()
174 | -> def doubler(a):
175 | (Pdb) break 6
176 | Breakpoint 1 at c:\py101\debug_test.py:6
177 | (Pdb) c
178 | > c:\py101\debug_test.py(6)doubler()
179 | -> result = a*2
180 | ```
181 |
182 | We start the debugger and then tell it to set a breakpoint on line 6.
183 | Then we continue and it stops on line 6 just like it's supposed to. Now
184 | would be a good time to check the argument list to see if it's what you
185 | expect. Give it a try by typing **args** now. Then do another
186 | **continue** and another **args** to see how it changed.
187 |
188 | Wrapping Up
189 | -----------
190 |
191 | There are a lot of other commands that you can use in the debugger. I
192 | recommend reading the documentation to learn about the others. However,
193 | at this point you should be able to use the debugger effectively to
194 | debug your own code.
195 |
--------------------------------------------------------------------------------
/manuscript/chapter26.txt:
--------------------------------------------------------------------------------
1 | # Chapter 26 - The lambda
2 |
3 | The Python lambda statement is an anonymous or unbound function and a
4 | pretty limited function at that. Let's take a look at a few typical
5 | examples and see if we can find a use case for it. The typical examples
6 | that one normally sees for teaching the lambda are some sort of boring
7 | doubling function. Just to be contrary, our simple example will show how
8 | to find the square root. First we'll show a normal function and then the
9 | lambda equivalent:
10 |
11 | ```python
12 | import math
13 |
14 | def sqroot(x):
15 | """
16 | Finds the square root of the number passed in
17 | """
18 | return math.sqrt(x)
19 |
20 | square_rt = lambda x: math.sqrt(x)
21 | ```
22 |
23 | If you try each of these functions, you'll end up with a float. Here are
24 | a couple examples:
25 |
26 | ```python
27 | >>> sqroot(49)
28 | 7.0
29 | >>> square_rt(64)
30 | 8.0
31 | ```
32 |
33 | Pretty slick, right? But where would we actually use a lambda in real
34 | life? Maybe a calculator program? Well, that would work, but it's a
35 | pretty limited application for a builtin of Python! One of the major
36 | pieces of Python that lambda examples are applied to regularly are
37 | Tkinter callbacks. Tkinter is a toolkit for building GUIs that is
38 | included with Python.
39 |
40 | Tkinter + lambda
41 | ----------------
42 |
43 | We'll start with Tkinter since it's included with the standard Python
44 | package. Here's a really simple script with three buttons, two of which
45 | are bound to their event handler using a lambda:
46 |
47 | ```python
48 | import Tkinter as tk
49 |
50 | class App:
51 | """"""
52 |
53 | def __init__(self, parent):
54 | """Constructor"""
55 | frame = tk.Frame(parent)
56 | frame.pack()
57 |
58 | btn22 = tk.Button(frame, text="22", command=lambda: self.printNum(22))
59 | btn22.pack(side=tk.LEFT)
60 | btn44 = tk.Button(frame, text="44", command=lambda: self.printNum(44))
61 | btn44.pack(side=tk.LEFT)
62 |
63 | quitBtn = tk.Button(frame, text="QUIT", fg="red", command=frame.quit)
64 | quitBtn.pack(side=tk.LEFT)
65 |
66 |
67 | def printNum(self, num):
68 | """"""
69 | print("You pressed the %s button" % num)
70 |
71 | if __name__ == "__main__":
72 | root = tk.Tk()
73 | app = App(root)
74 | root.mainloop()
75 | ```
76 |
77 | Notice the btn22 and btn44 variables. This is where the action is. We
78 | create a tk.Button instance here and bind to our printNum method in one
79 | fell swoop. The lambda is assigned to the button's command parameter.
80 | What this means is that we're creating a one-off function for the
81 | command, much like in the quit button where we call the frame's quit
82 | method. The difference here is that this particular lambda is a method
83 | that calls another method and passes the latter an integer. In the
84 | printNum method, we print to stdout which button was pressed by using
85 | the information that was passed to it from the lambda function. Did you
86 | follow all that? If so, we can continue; if not, re-read this paragraph
87 | as many times as necessary until the information sinks in or you go
88 | crazy, whichever comes first.
89 |
90 | Wrapping Up
91 | -----------
92 |
93 | The lambda statement is used in all kinds of other projects as well. If
94 | you Google a Python project name and lambda, you can find lots of live
95 | code out there. For example, if you search for "django lambda", you'll
96 | find out that django has a **modelformset** factory that utilizes
97 | lambdas. The Elixir plugin for SqlAlchemy also uses lambdas. Keep your
98 | eyes open and you'll be surprised how many times you'll stumble across
99 | this handy little function maker.
100 |
--------------------------------------------------------------------------------
/manuscript/chapter29.txt:
--------------------------------------------------------------------------------
1 | # Chapter 29 - Installing Modules
2 |
3 | When you're first starting out as a Python programmer, you don't think
4 | about how you might need to install an external package or module. But
5 | when that need appears, you'll want to know how to in a hurry! Python
6 | packages can be found all over the internet. Most of the popular ones
7 | can be found on the Python Package Index (PyPI). You will also find a
8 | lot of Python packages on github, bitbucket, and Google code. In this
9 | article, we will be covering the following methods of installing Python
10 | packages:
11 |
12 | > - Install from source
13 | > - easy\_install
14 | > - pip
15 | > - Other ways to install packages
16 |
17 | Installing from Source
18 | ----------------------
19 |
20 | Installing from source is a great skill to have. There are easier ways,
21 | which we'll be getting to later on in the article. However, there are
22 | some packages that you have to install from source. For example, to use
23 | **easy\_install**, you will need to first install **setuptools**. To do
24 | that, you will want to download the tar or zip file from the Python
25 | Package Index and extract it somewhere on your system. Then look for the
26 | **setup.py** file. Open up a terminal session and change directories to
27 | the folder that contains the setup file. Then run the following command:
28 |
29 | ```python
30 | python setup.py install
31 | ```
32 |
33 | If Python isn't on your system path, you will receive an error message
34 | stating that the *python* command wasn't found or is an unknown
35 | application. You can call this command by using the full path to Python
36 | instead. Here's how you might do it if you were on Windows:
37 |
38 | ```python
39 | c:\python34\python.exe setup.py install
40 | ```
41 |
42 | This method is especially handy if you have multiple versions of Python
43 | installed and you need to install the package to different ones. All you
44 | need to do is type the full path to the right Python version and install
45 | the package against it.
46 |
47 | Some packages contain C code, such as C header files that will need to
48 | be compiled for the package to install correctly. On Linux, you will
49 | normally already have a C/C++ compiler installed and you can get the
50 | package installed with minimal headaches. On Windows, you will need to
51 | have the correct version of Visual Studio installed to compile the
52 | package correctly. Some people say you can use MingW too, but I have yet
53 | to find a way to make that work. If the package has a Windows installer
54 | already pre-made, use it. Then you don't have to mess with compiling at
55 | all.
56 |
57 | Using easy\_install
58 | -------------------
59 |
60 | Once you have **setuptools** installed, you can use **easy\_install**.
61 | You can find it installed in your Python installation's **Scripts**
62 | folder. Be sure to add the Scripts folder to your system path so you can
63 | call easy\_install on the command line without specifying its full path.
64 | Try running the following command to learn about all of easy\_install's
65 | options:
66 |
67 | ```python
68 | easy_install -h
69 | ```
70 |
71 | When you want to install a package with easy\_install, all you have to
72 | do is this:
73 |
74 | ```python
75 | easy_install package_name
76 | ```
77 |
78 | easy\_install will attempt to download the package from PyPI, compile it
79 | (if necessary) and install it. If you go into your Python's
80 | **site-packages** directory, you will find a file named
81 | **easy-install.pth** that will contain an entry for all packages
82 | installed with easy\_install. This file is used by Python to help in
83 | importing the module or package.
84 |
85 | You can also tell easy\_install to install from a URL or from a path on
86 | your computer. It can also install packages directly from a tar file.
87 | You can use easy\_install to upgrade a package by using **-upgrade** (or
88 | **-U**). Finally, you can use easy\_install to install Python eggs. You
89 | can find egg files on PyPI and other locations. An egg is basically a
90 | special zip file. In fact, if you change the extension to .zip, you can
91 | unzip the egg file.
92 |
93 | Here are some examples:
94 |
95 | ```python
96 | easy_install -U SQLAlchemy
97 | easy_install http://example.com/path/to/MyPackage-1.2.3.tgz
98 | easy_install /path/to/downloaded/package
99 | ```
100 |
101 | There are some issues with easy\_install. It will try to install a
102 | package before it's finished downloading. There is no way to uninstall a
103 | package using easy\_install. You will have to delete the package
104 | yourself and update the easy-install.pth file by removing the entry to
105 | the package. For these reasons and others, there was movement in the
106 | Python community to create something different, which caused **pip** to
107 | be born.
108 |
109 | Using pip
110 | ---------
111 |
112 | The pip program actually comes with Python 3.4. If you have an older
113 | version of Python, then you will need to install pip manually.
114 | Installing pip is a little bit different than what we have previously
115 | discussed. You still go to PyPI, but instead of downloading the package
116 | and running its setup.py script, you will be asked to download a single
117 | script called **get-pip.py**. Then you will need to execute it by doing
118 | the following:
119 |
120 | ```python
121 | python get-pip.py
122 | ```
123 |
124 | This will install **setuptools** or an alternative to setuptools called
125 | **distribute** if one of them is not already installed. It will also
126 | install pip. pip works with CPython versions 2.6, 2.7, 3.1, 3.2, 3.3,
127 | 3.4 and also pypy. You can use pip to install anything that
128 | easy\_install can install, but the invocation is a bit different. To
129 | install a package, do the following:
130 |
131 | ```python
132 | pip install package_name
133 | ```
134 |
135 | To upgrade a package, you would do this:
136 |
137 | ```python
138 | pip install -U PackageName
139 | ```
140 |
141 | You may want to call **pip -h** to get a full listing of everything pip
142 | can do. One thing that pip can install that easy\_install cannot is the
143 | Python **wheel** format. A wheel is a ZIP-format archive with a
144 | specially formatted filename and the **.whl** extension. You can also
145 | install wheels via its own command line utility. On the other hand, pip
146 | cannot install an egg. If you need to install an egg, you will want to
147 | use easy\_install.
148 |
149 | A Note on Dependencies
150 | ----------------------
151 |
152 | One of the many benefits of using **easy\_install** and **pip** is that
153 | if the package has dependencies specified in their **setup.py** script,
154 | both **easy\_install** and **pip** will attempt to download and install
155 | them too. This can alleviate a lot of frustration when you're trying new
156 | packages and you didn't realize that package A depended on Packages B, C
157 | and D. With **easy\_install** or **pip**, you don't need to worry about
158 | that any more.
159 |
160 | Wrapping Up
161 | -----------
162 |
163 | At this point, you should be able to install just about any package that
164 | you need, assuming the package supports your version of Python. There
165 | are a lot of tools available to the Python programmer. While packaging
166 | in Python is a bit confusing right now, once you know how to use the
167 | proper tools, you can usually get what you want installed or packaged
168 | up. We will be looking more at creating our own packages, eggs and
169 | wheels in Part V.
170 |
--------------------------------------------------------------------------------
/manuscript/chapter33.txt:
--------------------------------------------------------------------------------
1 | # Chapter 33 - The requests package
2 |
3 | The **requests** package is a more Pythonic replacement for Python's own
4 | **urllib**. You will find that requests package's API is quite a bit
5 | simpler to work with. You can install the requests library by using pip
6 | or easy\_install or from source.
7 |
8 | Using requests
9 | --------------
10 |
11 | Let's take a look at a few examples of how to use the requests package.
12 | We will use a series of small code snippets to help explain how to use
13 | this library.
14 |
15 | ```python
16 | >>> r = requests.get("http://www.google.com")
17 | ```
18 |
19 | This example returns a **Response** object. You can use the Response
20 | object's methods to learn a lot about how you can use requests. Let's
21 | use Python's **dir** function to find out what methods we have
22 | available:
23 |
24 | ```python
25 | >>> dir(r)
26 | ['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__',
27 | '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
28 | '__getstate__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__lt__',
29 | '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__',
30 | '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__',
31 | '__weakref__', '_content', '_content_consumed', 'apparent_encoding', 'close',
32 | 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history',
33 | 'iter_content', 'iter_lines', 'json', 'links', 'ok', 'raise_for_status', 'raw',
34 | 'reason', 'request', 'status_code', 'text', 'url']
35 | ```
36 |
37 | If you run the following method, you can see the web page's source code:
38 |
39 | ```python
40 | >>> r.content()
41 | ```
42 |
43 | The output from this command is way too long to include in the book, so
44 | be sure to try it out yourself. If you'd like to take a look at the web
45 | pages headers, you can run the following:
46 |
47 | ```python
48 | >>> r.headers
49 | ```
50 |
51 | Note that the **headers** attribute returns a dict-like object and isn't
52 | a function call. We're not showing the output as web page headers tend
53 | to be too wide to show correctly in a book. There are a bunch of other
54 | great functions and attributes in the Response object. For example, you
55 | can get the cookies, the links in the page, and the status\_code that
56 | the page returned.
57 |
58 | The requests package supports the following HTTP request types: POST,
59 | GET, PUT, DELETE, HEAD and OPTIONS. If the page returns json, you can
60 | access it by calling the Response object's **json** method. Let's take a
61 | look at a practical example.
62 |
63 | How to Submit a Web Form
64 | ------------------------
65 |
66 | In this section, we will compare how to submit a web form with requests
67 | versus urllib. Let's start by learning how to submit a web form. We will
68 | be doing a web search with **duckduckgo.com** searching on the term
69 | *python* and saving the result as an HTML file. We'll start with an
70 | example that uses urllib:
71 |
72 | ```python
73 | import urllib.request
74 | import urllib.parse
75 | import webbrowser
76 |
77 | data = urllib.parse.urlencode({'q': 'Python'})
78 | url = 'http://duckduckgo.com/html/'
79 | full_url = url + '?' + data
80 | response = urllib.request.urlopen(full_url)
81 | with open("results.html", "wb") as f:
82 | f.write(response.read())
83 |
84 | webbrowser.open("results.html")
85 | ```
86 |
87 | The first thing you have to do when you want to submit a web form is
88 | figure out what the form is called and what the url is that you will be
89 | posting to. If you go to duckduckgo's website and view the source,
90 | you'll notice that its action is pointing to a relative link, "/html".
91 | So our url is "". The input field is named
92 | "q", so to pass duckduckgo a search term, we have to concatenate the url
93 | to the "q" field. The results are read and written to disk. Now let's
94 | find out how this process differs when using the requests package.
95 |
96 | The requests package does form submissions a little bit more elegantly.
97 | Let's take a look:
98 |
99 | ```python
100 | import requests
101 |
102 | url = 'https://duckduckgo.com/html/'
103 | payload = {'q':'python'}
104 | r = requests.get(url, params=payload)
105 | with open("requests_results.html", "wb") as f:
106 | f.write(r.content)
107 | ```
108 |
109 | With requests, you just need to create a dictionary with the field name
110 | as the key and the search term as the value. Then you use
111 | **requests.get** to do the search. Finally you use the resulting
112 | requests object, "r", and access its content property which you save to
113 | disk.
114 |
115 | Wrapping Up
116 | -----------
117 |
118 | Now you know the basics of the **requests** package. I would recommend
119 | reading the package's online documentation as it has many additional
120 | examples that you may find useful. I personally think this module is
121 | more intuitive to use than the standard library's equivalent.
122 |
--------------------------------------------------------------------------------
/manuscript/chapter35.txt:
--------------------------------------------------------------------------------
1 | # Chapter 35 - virtualenv
2 |
3 | Virtual environments can be really handy for testing software. That's
4 | true in programming circles too. Ian Bicking created the virtualenv
5 | project, which is a tool for creating isolated Python environments. You
6 | can use these environments to test out new versions of your software,
7 | new versions of packages you depend on or just as a sandbox for trying
8 | out some new package in general. You can also use virtualenv as a
9 | workspace when you can't copy files into site-packages because it's on a
10 | shared host. When you create a virtual environment with virtualenv, it
11 | creates a folder and copies Python into it along with a site-packages
12 | folder and a couple others. It also installs pip. Once your virtual
13 | environment is active, it's just like using your normal Python. And when
14 | you're done, you can just delete the folder to cleanup. No muss, no
15 | fuss. Alternatively, you can keep on using it for development.
16 |
17 | In this chapter, we'll spend some time getting to know virtualenv and
18 | how to use it to make our own magic.
19 |
20 | Installation
21 | ------------
22 |
23 | First of all, you probably need to install virtualenv. You can use pip
24 | or easy\_install to install it or you can download the virtualenv.py
25 | file from their website and install it from source using its
26 | **setup.py** script.
27 |
28 | If you have Python 3.4, you will find that you actually have the
29 | **venv** module, which follows an API that is very similar to the
30 | **virtualenv** package. This chapter will focus on just the virtualenv
31 | package, however.
32 |
33 | Creating a Virtual Environment
34 | ------------------------------
35 |
36 | Creating a virtual sandbox with the virtualenv package is quite easy.
37 | All you need to do is the following:
38 |
39 | ```python
40 | python virtualenv.py FOLDER_NAME
41 | ```
42 |
43 | Where **FOLDER\_NAME** is the name of the folder that you want your
44 | sandbox to go. On my Windows 7 machine, I have **C:\\Python34\\Scripts**
45 | added to my path so I can just call **virtualenv.py** FOLDER\_NAME
46 | without the python part. If you don't pass it anything, then you'll get
47 | a list of options printed out on your screen. Let's say we create a
48 | project called **sandbox**. How do we use it? Well, we need to
49 | **activate**. it. Here's how:
50 |
51 | On Posix you would do source bin/activate while on Windows, you would do
52 | **.\\path\\to\\env\\Scripts\\activate**. on the command line. Let's
53 | actually go through these steps. We'll create the sandbox folder on our
54 | desktop so you can see an example. Here's what it looks like on my
55 | machine:
56 |
57 | ```python
58 | C:\Users\mdriscoll\Desktop>virtualenv sandbox
59 | New python executable in sandbox\Scripts\python.exe
60 | Installing setuptools................done.
61 | Installing pip...................done.
62 |
63 | C:\Users\mdriscoll\Desktop>sandbox\Scripts\activate
64 | (sandbox) C:\Users\mdriscoll\Desktop>
65 | ```
66 |
67 | You'll note that once your virtual environment is activated, you'll see
68 | your prompt change to include a prefix of the folder name that you
69 | created, which is **sandbox** in this case. This lets you know that
70 | you're using your sandbox. Now you can use pip to install other packages
71 | to your virtual environment. When you're done, you just call the
72 | deactivate script to exit the environment.
73 |
74 | There are a couple of flags you can pass to virtualenv when creating
75 | your virtual playground that you should be aware of. For example, you
76 | can use **-system-site-packages** to inherit the packages from your
77 | default Python's site packages. If you want to use distribute rather
78 | than setuptools, you can pass virtualenv the **-distribute** flag.
79 |
80 | virtualenv also provides a way for you to just install libraries but use
81 | the system Python itself to run them. According to the documentation,
82 | you just create a special script to do it.
83 |
84 | There's also a neat (and experimental) flag called **-relocatable** that
85 | can be used to make the folder relocatable. However, this does NOT work
86 | on Windows at the time of this writing, so I wasn't able to test it out.
87 |
88 | Finally, there's an **-extra-search-dir** flag that you can use to keep
89 | your virtual environment offline. Basically it allows you to add a
90 | directory to the search path for distributions that pip or easy\_install
91 | can install from. In this way, you don't need to have access to the
92 | internet to install packages.
93 |
94 | Wrapping Up
95 | -----------
96 |
97 | At this point, you should be able to use virtualenv yourself. There are
98 | a couple of other projects worth mentioning at this point. There's Doug
99 | Hellman's **virtualenvwrapper** library that makes it even easier to
100 | create, delete and manage virtual environments and then there's
101 | **zc.buildout** which is probably the closest thing to virtualenv that
102 | could be called a competitor. I recommend checking them both out as they
103 | might help you in your programming adventures.
104 |
--------------------------------------------------------------------------------
/manuscript/chapter36.txt:
--------------------------------------------------------------------------------
1 | # Chapter 36 - Creating Modules and Packages
2 |
3 | Creating Python modules is something that most Python programmers do
4 | every day without even thinking about it. Any time you save a new Python
5 | script, you have created a new module. You can import your module into
6 | other modules. A package is a collection of related modules. The things
7 | you import into your scripts from the standard library are modules or
8 | packages. In this chapter, we will learn how to create modules and
9 | packages. We'll spend more time on packages since they're more
10 | complicated than modules.
11 |
12 | How to Create a Python Module
13 | -----------------------------
14 |
15 | We will begin by creating a super simple module. This module will
16 | provide us with basic arithmetic and no error handling. Here's our first
17 | example:
18 |
19 | ```python
20 | def add(x, y):
21 | return x + y
22 |
23 | def division(x, y):
24 | return x / y
25 |
26 | def multiply(x, y):
27 | return x * y
28 |
29 | def subtract(x, y):
30 | return x - y
31 | ```
32 |
33 | This code has issues, of course. If you pass in two Integers to the
34 | **division** method, then you'll end up getting an Integer back if you
35 | are using Python 2.x. This may not be what you're expecting. There's
36 | also no error checking for division by zero or mixing of strings and
37 | numbers. But that's not the point. The point is that if you save this
38 | code, you have a fully qualified module. Let's call it
39 | **arithmetic.py**. Now what can you do with a module anyway? You can
40 | import it and use any of the defined functions or classes that are
41 | inside it. And we could make it **executable** with a little spit and
42 | polish. Let's do both!
43 |
44 | First we'll write a little script that imports our module and runs the
45 | functions in it. Save the following as **math\_test.py**:
46 |
47 | ```python
48 | import arithmetic
49 |
50 | print(arithmetic.add(5, 8))
51 | print(arithmetic.subtract(10, 5))
52 | print(arithmetic.division(2, 7))
53 | print(arithmetic.multiply(12, 6))
54 | ```
55 |
56 | Now let's modify the original script so that we can run it from the
57 | command line. Here's one of the simplest ways to do it:
58 |
59 | ```python
60 | def add(x, y):
61 | return x + y
62 |
63 | def division(x, y):
64 | return x / y
65 |
66 | def multiply(x, y):
67 | return x * y
68 |
69 | def subtract(x, y):
70 | return x - y
71 |
72 | if __name__ == "__main__":
73 | import sys
74 | print(sys.argv)
75 | v = sys.argv[1].lower()
76 | valOne = int(sys.argv[2])
77 | valTwo = int(sys.argv[3])
78 | if v == "a":
79 | print(add(valOne, valTwo))
80 | elif v == "d":
81 | print(division(valOne, valTwo))
82 | elif v == "m":
83 | print(multiply(valOne, valTwo))
84 | elif v == "s":
85 | print(subtract(valOne, valTwo))
86 | else:
87 | pass
88 | ```
89 |
90 | The proper way to do this script would be to use Python's **optparse
91 | (pre-2.7)** or **argparse (2.7+)** module. You should spend some time to
92 | figure out one of these modules as a learning exercise. In the meantime,
93 | we will move on to packages!
94 |
95 | How to Create a Python Package
96 | ------------------------------
97 |
98 | The main difference between a module and a package is that a package is
99 | a collection of modules AND it has an **\_\_init\_\_.py** file.
100 | Depending on the complexity of the package, it may have more than one
101 | **\_\_init\_\_.py**. Let's take a look at a simple folder structure to
102 | make this more obvious, then we'll create some simple code to follow the
103 | structure we define.
104 |
105 | ```python
106 | mymath/
107 | __init__.py
108 | adv/
109 | __init__.py
110 | sqrt.py
111 | add.py
112 | subtract.py
113 | multiply.py
114 | divide.py
115 | ```
116 |
117 | Now we just need to replicate this structure in our own package. Let's
118 | give that a whirl! Create each of these files in a folder tree like the
119 | above example. For the add, subtract, multiply and divide files, you can
120 | use the functions we created in the earlier example. For the **sqrt.py**
121 | module, we'll use the following code.
122 |
123 | ```python
124 | # sqrt.py
125 | import math
126 |
127 | def squareroot(n):
128 | return math.sqrt(n)
129 | ```
130 |
131 | You can leave both **\_\_init\_\_.py** files blank, but then you'll have
132 | to write code like **mymath.add.add(x,y)** which is pretty ugly, so
133 | we'll add the following code to the outer **\_\_init\_\_.py** to make
134 | using our package easier to understand and use.
135 |
136 | ```python
137 | # outer __init__.py
138 | from . add import add
139 | from . divide import division
140 | from . multiply import multiply
141 | from . subtract import subtract
142 | from .adv.sqrt import squareroot
143 | ```
144 |
145 | Now we should be able to use our module once we have it on our Python
146 | path. You can copy the folder into your Python's **site-packages**
147 | folder to do this. On Windows it's in the following general location:
148 | **C:\\Python34\\Lib\\site-packages**. Alternatively, you can edit the
149 | path on the fly in your test code. Let's see how that's done:
150 |
151 | ```python
152 | import sys
153 |
154 | # modify this path to match your environment
155 | sys.path.append('C:\Users\mdriscoll\Documents')
156 |
157 | import mymath
158 |
159 | print(mymath.add(4,5))
160 | print(mymath.division(4, 2))
161 | print(mymath.multiply(10, 5))
162 | print(mymath.squareroot(48))
163 | ```
164 |
165 | Note that my path does NOT include the **mymath** folder. You want to
166 | append the parent folder that holds your new module, NOT the module
167 | folder itself. If you do this, then the code above should work.
168 |
169 | You can also create a **setup.py** script and install your package in
170 | **develop** mode. Here's an example setup.py script:
171 |
172 | ```python
173 | #!/usr/bin/env python
174 |
175 | from setuptools import setup
176 |
177 |
178 | # This setup is suitable for "python setup.py develop".
179 |
180 | setup(name='mymath',
181 | version='0.1',
182 | description='A silly math package',
183 | author='Mike Driscoll',
184 | author_email='mike@mymath.org',
185 | url='http://www.mymath.org/',
186 | packages=['mymath', 'mymath.adv'],
187 | )
188 | ```
189 |
190 | You would save this script one level above the **mymath** folder. To
191 | install the package in develop mode, you would do the following:
192 |
193 | ```python
194 | python setup.py develop
195 | ```
196 |
197 | This will install a link file in the site-packages folder that points to
198 | where ever your package resides. This is great for testing without
199 | actually installing your package.
200 |
201 | Congratulations! You've just created a Python package!
202 |
203 | Wrapping Up
204 | -----------
205 |
206 | You've just learned how to create your very own, custom-made modules and
207 | packages. You will find that the more you code, the more often you'll
208 | create programs that have parts that you want to re-use. You can put
209 | those reusable pieces of code into modules. Eventually you will have
210 | enough related modules that you may want to turn them into a package.
211 | Now you have the tools to actually do that!
212 |
--------------------------------------------------------------------------------
/manuscript/chapter37.txt:
--------------------------------------------------------------------------------
1 | # Chapter 37 - How to Add Your Code to PyPI
2 |
3 | We created a package called **mymath** in the previous chapter. In this
4 | chapter, we will learn how to share it on the Python Packaging Index
5 | (PyPI). To do that, we will first need to learn how to create a
6 | **setup.py** file. Just to review, here is our current folder hierarchy:
7 |
8 | ```python
9 | mymath/
10 | __init__.py
11 | adv/
12 | __init__.py
13 | sqrt.py
14 | add.py
15 | subtract.py
16 | multiply.py
17 | divide.py
18 | ```
19 |
20 | This means that you have a **mymath** folder with the following files in
21 | it: **\_\_init\_\_.py, add.py, subtract.py, multiply.py** and
22 | **divide.py**. You will also have an **adv** folder inside the
23 | **mymath** folder. In the **adv** folder, you will have two files:
24 | **\_\_init\_\_.py** and **sqrt.py**.
25 |
26 | Creating a setup.py File
27 | ------------------------
28 |
29 | We will start out by creating a super simple **setup.py** script. Here's
30 | a bare-bones one:
31 |
32 | ```python
33 | from distutils.core import setup
34 |
35 | setup(name='mymath',
36 | version='0.1',
37 | packages=['mymath', 'mymath.adv'],
38 | )
39 | ```
40 |
41 | This is something you might write for a package internally. To upload to
42 | PyPI, you will need to include a little more information:
43 |
44 | ```python
45 | from distutils.core import setup
46 |
47 | setup(name='mymath',
48 | version='0.1',
49 | description='A silly math package',
50 | author='Mike Driscoll',
51 | author_email='mike@mymath.org',
52 | url='http://www.mymath.org/',
53 | packages=['mymath', 'mymath.adv'],
54 | )
55 | ```
56 |
57 | Now that we're done with that, we should test our script. You can create
58 | a virtual environment using the directions from chapter 35 or you can
59 | just install your code to your Python installation by calling the
60 | following command:
61 |
62 | ```python
63 | python setup.py install
64 | ```
65 |
66 | Alternatively, you can use the method at the end of the last chapter in
67 | which you created a special **setup.py** that you installed in
68 | **develop** mode. You will note that in the last chapter, we used
69 | **setuptools** whereas in this chapter we used **distutils**. The only
70 | reason we did this is that setuptools has the **develop** command and
71 | distutils does not.
72 |
73 | Now we need to register our package with PyPI!
74 |
75 | Registering Packages
76 | --------------------
77 |
78 | Registering you package is very easy. Since this is your first package,
79 | you will want to register with the Test PyPI server instead of the real
80 | one. You may need to create a **.pypirc** file and enter the Test PyPI
81 | server address. See the next section for more information. Once you have
82 | done that, you just need to run the following command:
83 |
84 | ```python
85 | python setup.py register
86 | ```
87 |
88 | You will receive a list of options that ask you to login, register, have
89 | the server send you a password or quit. If you have your username and
90 | password saved on your machine, you won't see that message. If you're
91 | already registered, you can login and your package's metadata will be
92 | uploaded.
93 |
94 | Uploading Packages to PyPI
95 | --------------------------
96 |
97 | You will probably want to start out by testing with PyPI's test server,
98 | which is at . You will have to
99 | register with that site too as it uses a different database than the
100 | main site. Once you've done that, you may want to create a **.pypirc**
101 | file somewhere on your operating system's path. On Linux, you can use
102 | **\$HOME** to find it and on Windows, you can use the **HOME** environ
103 | variable. This path is where you would save that file. Following is a
104 | sample of what could go in your pypirc file from
105 | :
106 |
107 | ```python
108 | [distutils]
109 | index-servers=
110 | pypi
111 | test
112 |
113 | [test]
114 | repository = https://testpypi.python.org/pypi
115 | username = richard
116 | password =
117 |
118 | [pypi]
119 | repository = http://pypi.python.org/pypi
120 | username = richard
121 | password =
122 | ```
123 |
124 | I would highly recommend that you read the documentation in depth to
125 | understand all the options you can add to this configuration file.
126 |
127 | To upload some files to PyPI, you will need to create some
128 | distributions.
129 |
130 | ```python
131 | python setup.py sdist bdist_wininst upload
132 | ```
133 |
134 | When you run the command above, it will create a **dist** folder. The
135 | **sdist** command will create an archive file (a zip on Windows, a
136 | tarball on Linux). The **bdist\_wininst** will create a simple Windows
137 | installer executable. The **upload** command will then upload these two
138 | files to PyPI.
139 |
140 | In your **setup.py** file, you can add a **long\_description** field
141 | that will be used by PyPI to generate a home page for your package on
142 | PyPI. You can use reStructuredText to format your description. Or you
143 | can skip adding the description and accept PyPI's default formatting.
144 |
145 | If you would like a full listing of the commands you can use with
146 | **setup.py**, try running the following command:
147 |
148 | ```python
149 | python setup.py --help-commands
150 | ```
151 |
152 | You should also add a **README.txt** file that explains how to install
153 | and use your package. It can also contain a "Thank You" section if you
154 | have a lot of contributors.
155 |
156 | Wrapping Up
157 | -----------
158 |
159 | Now you know the basics for adding your package to the Python Packaging
160 | Index. If you want to add a Python egg to PyPI, you will need to use
161 | easy\_install instead of distutils. When you release your next version,
162 | you may want to add a **CHANGES.txt** file that lists the changes to
163 | your code. There is a great website called **The Hitchhiker's Guide to
164 | Packaging** which would be a great place for you to check out for
165 | additional information on this exciting topic. Alternatively, you may
166 | also want to check out this
167 | [tutorial](http://www.scotttorborg.com/python-packaging/index.html) by
168 | Scott Torborg to get a different take on the process.
169 |
--------------------------------------------------------------------------------
/manuscript/chapter38.txt:
--------------------------------------------------------------------------------
1 | # Chapter 38 - The Python egg
2 |
3 | Python **eggs** are an older distribution format for Python. The new
4 | format is called a Python **wheel**, which we will look at in the next
5 | chapter. An egg file is basically a zip file with a different extension.
6 | Python can import directly from an egg. You will need the **SetupTools**
7 | package to work with eggs. SetupTools is the original mainstream method
8 | of downloading and installing Python packages from PyPI and other
9 | sources via the command line, kind of like apt-get for Python. There was
10 | a fork of SetupTools called **distribute** that was eventually merged
11 | back into SetupTools. I only mention it because you may see references
12 | to that fork if you do much reading about Python eggs outside of this
13 | book.
14 |
15 | While the egg format is being migrated away from, you do still need to
16 | know about it as there are many packages that are distributed using this
17 | technology. It will probably be years before everyone has stopped using
18 | eggs. Let's learn how to make our own!
19 |
20 | Creating an egg
21 | ---------------
22 |
23 | You can think of an egg as just an alternative to a source distribution
24 | or Windows executable, but it should be noted that for pure Python eggs,
25 | the egg file is completely cross-platform. We will take a look at how to
26 | create our own egg using the package we created in a previous modules
27 | and packages chapter. To get started creating an egg, you will need to
28 | create a new folder and put the **mymath** folder inside it. Then create
29 | a **setup.py** file in the parent directory to mymath with the following
30 | contents:
31 |
32 | ```python
33 | from setuptools import setup, find_packages
34 |
35 | setup(
36 | name = "mymath",
37 | version = "0.1",
38 | packages = find_packages()
39 | )
40 | ```
41 |
42 | Python has its own package for creating distributions that is called
43 | **distutils**. However instead of using Python's **distutils' setup**
44 | function, we're using **setuptools' setup**. We're also using
45 | setuptools' **find\_packages** function which will automatically look
46 | for any packages in the current directory and add them to the egg. To
47 | create said egg, you'll need to run the following from the command line:
48 |
49 | ```python
50 | c:\Python34\python.exe setup.py bdist_egg
51 | ```
52 |
53 | This will generate a lot of output, but when it's done you'll see that
54 | you have three new folders: **build**, **dist**, and
55 | **mymath.egg-info**. The only one we care about is the **dist** folder
56 | in which you will find your egg file, **mymath-0.1-py3.4.egg**. Note
57 | that on my machine, I forced it to run against Python 3.4 so that it
58 | would create the egg against that version of Python. The egg file itself
59 | is basically a zip file. If you change the extension to "zip", you can
60 | look inside it and see that it has two folders: **mymath** and
61 | **EGG-INFO**. At this point, you should be able to point
62 | **easy\_install** at your egg on your file system and have it install
63 | your package.
64 |
65 | Wrapping Up
66 | -----------
67 |
68 | Now it's your turn. Go onto the Python Package Index and find some pure
69 | Python modules to download. Then try creating eggs using the techniques
70 | you learned in this chapter. If you want to install an egg, you can use
71 | **easy\_install**. Uninstalling an egg is a bit tougher. You will have
72 | to go to its install location and delete the folder and / or egg file it
73 | installed as well as remove the entry for the package from the
74 | **easy-install.pth** file. All of these items can be found in your
75 | Python's **site-packages** folder.
76 |
--------------------------------------------------------------------------------
/manuscript/chapter39.txt:
--------------------------------------------------------------------------------
1 | # Chapter 39 - Python wheels
2 |
3 | Python's first mainstream packaging format was the .egg file. Now
4 | there's a new format in town called the **wheel** (*.whl). According to
5 | the Python Packaging Index's description, a wheel*is designed to contain
6 | all the files for a PEP 376 compatible install in a way that is very
7 | close to the on-disk format\*. In this chapter, we will learn how to
8 | create a wheel and then install our wheel in a **virtualenv**.
9 |
10 | Getting Started
11 | ---------------
12 |
13 | Using pip is the recommended way to work with wheels. Make sure you have
14 | installed the latest copy of pip as older versions did not support the
15 | wheel format. If you're not sure if you have the latest pip, you can run
16 | the following command:
17 |
18 | ```python
19 | pip install --upgrade pip
20 | ```
21 |
22 | If you didn't have the latest, then this command will upgrade pip. Now
23 | we're ready to create a wheel!
24 |
25 | Creating a wheel
26 | ----------------
27 |
28 | First of all, you will need to install the wheel package:
29 |
30 | ```python
31 | pip install wheel
32 | ```
33 |
34 | That was easy! Next, we'll be using the **unidecode** package for
35 | creating our first wheel as it doesn't already have one made at the time
36 | of writing and I've used this package myself in several projects. The
37 | unidecode package will take a string of text and attempt to replace any
38 | unicode with its ASCII equivalent. This is extremely handy for when you
39 | have to scrub user provided data of weird anomalies. Here's the command
40 | you should run to create a wheel for this package:
41 |
42 | ```python
43 | pip wheel --wheel-dir=my_wheels Unidecode
44 | ```
45 |
46 | Here's a screenshot of the output I received when I ran this:
47 |
48 | 
49 |
50 | Now you should have a wheel named
51 | **Unidecode-0.04.14-py26-none-any.whl** in a folder named my\_wheels.
52 | Let's learn how to install our new wheel!
53 |
54 | Installing a Python wheel
55 | -------------------------
56 |
57 | Let's create a virtualenv to test with. We will use the following
58 | command to create our virtual testing environment:
59 |
60 | ```python
61 | virtualenv test
62 | ```
63 |
64 | This assumes that **virtualenv** is on your system path. If you get an
65 | **unrecognized command** error, then you'll probably have to specify the
66 | full path (i.e. **c:\\Python34\\Scripts\\virtualenv**). Running this
67 | command will create a virtual sandbox for us to play in that includes
68 | pip. Be sure to run the **activate** script from the **test** folder's
69 | Scripts folder to enable the virtuanenv before continuing. Your
70 | virtualenv does not include wheel, so you'll have to install wheel
71 | again:
72 |
73 | ```python
74 | pip install wheel
75 | ```
76 |
77 | Once that is installed, we can install our wheel with the following
78 | command:
79 |
80 | ```python
81 | pip install --no-index --find-links=path/to/my_wheels Unidecode
82 | ```
83 |
84 | To test that this worked, run Python from the Scripts folder in your
85 | virtualenv and try importing unidecode. If it imports, then you
86 | successfully installed your wheel!
87 |
88 | The *.whl file is similar to an*.egg in that it's basically a *.zip file
89 | in disguise. If you rename the extension from*.whl to \*.zip, you can
90 | open it up with your zip application of choice and examine the files and
91 | folders inside at your leisure.
92 |
93 | Wrapping Up
94 | -----------
95 |
96 | Now you should be ready to create your own wheels. They are a nice way
97 | to create a local repository of dependencies for your project(s) that
98 | you can install quickly. You could create several different wheel
99 | repositories to easily switch between different version sets for testing
100 | purposes. When combined with virtualenv, you have a really easy way to
101 | see how newer versions of dependencies could affect your project without
102 | needing to download them multiple times.
103 |
--------------------------------------------------------------------------------
/manuscript/chapter6.txt:
--------------------------------------------------------------------------------
1 | # Chapter 6 - Python Comprehensions
2 |
3 | The Python language has a couple of methods for creating lists and
4 | dictionaries that are known as comprehensions. There is also a third
5 | type of comprehension for creating a Python set. In this chapter we will
6 | learn how to use each type of comprehension. You will find that the
7 | comprehension constructs build on the knowledge you have acquired from
8 | the previous chapters as they contain loops and conditionals themselves.
9 |
10 | List Comprehensions
11 | -------------------
12 |
13 | List comprehensions in Python are very handy. They can also be a little
14 | hard to understand when and why you would use them. List comprehensions
15 | tend to be harder to read than just using a simple **for** loop as well.
16 | You may want to review the looping chapter before you continue.
17 |
18 | If you are ready, then we'll spend some time looking at how to construct
19 | list comprehensions and learn how they can be used. A list comprehension
20 | is basically a one line **for** loop that produces a Python **list**
21 | data structure. Here's a simple example:
22 |
23 | ```python
24 | >>> x = [i for i in range(5)]
25 | ```
26 |
27 | Let's break this down a bit. Python comes with a range function that can
28 | return a list of numbers. By default, it returns integers starting at 0
29 | and going up to but not including the number you pass it. So in this
30 | case, it returns a list containing the integers 0-4. This can be useful
31 | if you need to create a list very quickly. For example, say you're
32 | parsing a file and looking for something in particular. You could use a
33 | list comprehension as a kind of filter:
34 |
35 | ```python
36 | if [i for i in line if "SOME TERM" in i]:
37 | # do something
38 | ```
39 |
40 | I have used code similar to this to look through a file quickly to parse
41 | out specific lines or sections of the file. When you throw functions
42 | into the mix, you can start doing some really cool stuff. Say you want
43 | to apply a function to every element in a list, such as when you need to
44 | cast a bunch of strings into integers:
45 |
46 | ```python
47 | >>> x = ['1', '2', '3', '4', '5']
48 | >>> y = [int(i) for i in x]
49 | >>> y
50 | [1, 2, 3, 4, 5]
51 | ```
52 |
53 | This sort of thing comes up more often than you'd think. I have also had
54 | to loop over a list of strings and call a string method, such as strip
55 | on them because they had all kinds of leading or ending white space:
56 |
57 | ```python
58 | >>> myStrings = [s.strip() for s in myStringList]
59 | ```
60 |
61 | There are also occasions where one needs to create a nested list
62 | comprehension. One reason to do that is to flatten multiple lists into
63 | one. This example comes from the Python documentation:
64 |
65 | ```python
66 | >>> vec = [[1,2,3], [4,5,6], [7,8,9]]
67 | >>> [num for elem in vec for num in elem]
68 | [1, 2, 3, 4, 5, 6, 7, 8, 9]
69 | ```
70 |
71 | The documentation shows several other interesting examples for nested
72 | list comprehensions as well. I highly recommend taking a look at it! At
73 | this point, you should now be capable of using list comprehensions in
74 | your own code and use them well. Just use your imagination and you'll
75 | start seeing lots of good places where you too can use them.
76 |
77 | Now we're ready to move on to Python's dictionary comprehensions!
78 |
79 | Dictionary Comprehensions
80 | -------------------------
81 |
82 | Dictionary comprehensions started life in Python 3.0, but were
83 | backported to Python 2.7. They were originally proposed in the [Python
84 | Enhancement Proposal 274 (PEP
85 | 274)](http://www.python.org/dev/peps/pep-0274/) back in 2001. They are
86 | pretty similar to a list comprehension in the way that they are
87 | organized.
88 |
89 | The best way to understand is to just do one!
90 |
91 | ```python
92 | >>> print( {i: str(i) for i in range(5)} )
93 | {0: '0', 1: '1', 2: '2', 3: '3', 4: '4'}
94 | ```
95 |
96 | This is a pretty straightforward comprehension. Basically it is creating
97 | an integer key and string value for each item in the range. Now you may
98 | be wondering how you could use a dictionary comprehension in real life.
99 | [Mark Pilgrim](http://www.diveintopython3.net/comprehensions.html)
100 | mentioned that you could use a dictionary comprehension for swapping the
101 | dictionary's keys and values. Here's how you would do that:
102 |
103 | ```python
104 | >>> my_dict = {1:"dog", 2:"cat", 3:"hamster"}
105 | >>> print( {value:key for key, value in my_dict.items()} )
106 | {'hamster': 3, 'dog': 1, 'cat': 2}
107 | ```
108 |
109 | This will only work if the dictionary values are of a non-mutable type,
110 | such as a string. Otherwise you will end up causing an exception to be
111 | raised.
112 |
113 | I could also see a dictionary comprehension being useful for creating a
114 | table out of class variables and their values. However, we haven't
115 | covered classes at this point, so I won't confuse you with that here.
116 |
117 | Set Comprehensions
118 | ------------------
119 |
120 | Set comprehensions are created in much the same way as dictionary
121 | comprehensions. Now a Python set is much like a mathematical set in that
122 | it doesn't have any repeated elements. You can create a normal set like
123 | this:
124 |
125 | ```python
126 | >>> my_list = [1, 2, 2, 3, 4, 5, 5, 7, 8]
127 | >>> my_set = set(my_list)
128 | >>> my_set
129 | set([1, 2, 3, 4, 5, 7, 8])
130 | ```
131 |
132 | As you can see from the example above, the call to set has removed the
133 | duplicates from the list. Now let's rewrite this code to use a set
134 | comprehension:
135 |
136 | ```python
137 | >>> my_list = [1, 2, 2, 3, 4, 5, 5, 7, 8]
138 | >>> my_set = {x for x in my_list}
139 | >>> my_set
140 | set([1, 2, 3, 4, 5, 7, 8])
141 | ```
142 |
143 | You will notice that to create a set comprehension, we basically changed
144 | the square brackets that a list comprehension uses to the curly braces
145 | that the dictionary comprehension has.
146 |
147 | Wrapping Up
148 | -----------
149 |
150 | Now you know how to use the various Python comprehensions. You will
151 | probably find the list comprehension the most useful at first and also
152 | the most popular. If you start using your imagination, I am sure you
153 | will be able to find uses for all three types of comprehensions. Now
154 | we're ready to move on and learn about exception handling!
155 |
--------------------------------------------------------------------------------
/manuscript/chapter9.txt:
--------------------------------------------------------------------------------
1 | # Chapter 9 - Importing
2 |
3 | Python comes with lots of pre-made code baked in. These pieces of code
4 | are known as modules and packages. A module is a single importable
5 | Python file whereas a package is made up of two or more modules. A
6 | package can be imported the same way a module is. Whenever you save a
7 | Python script of your own, you have created a module. It may not be a
8 | very useful module, but that's what it is. In this chapter, we will
9 | learn how to import modules using several different methods. Let's get
10 | started!
11 |
12 | import this
13 | -----------
14 |
15 | Python provides the **import** keyword for importing modules. Let's give
16 | it a try:
17 |
18 | ```python
19 | import this
20 | ```
21 |
22 | If you run this code in your interpreter, you should see something like
23 | the following as your output:
24 |
25 | ```python
26 | The Zen of Python, by Tim Peters
27 |
28 | Beautiful is better than ugly.
29 | Explicit is better than implicit.
30 | Simple is better than complex.
31 | Complex is better than complicated.
32 | Flat is better than nested.
33 | Sparse is better than dense.
34 | Readability counts.
35 | Special cases aren't special enough to break the rules.
36 | Although practicality beats purity.
37 | Errors should never pass silently.
38 | Unless explicitly silenced.
39 | In the face of ambiguity, refuse the temptation to guess.
40 | There should be one-- and preferably only one --obvious way to do it.
41 | Although that way may not be obvious at first unless you're Dutch.
42 | Now is better than never.
43 | Although never is often better than *right* now.
44 | If the implementation is hard to explain, it's a bad idea.
45 | If the implementation is easy to explain, it may be a good idea.
46 | Namespaces are one honking great idea -- let's do more of those!
47 | ```
48 |
49 | You have found an "Easter egg" in Python known as the "Zen of Python".
50 | It's actually a sort of an unofficial best practices for Python. The
51 | **this** module doesn't actually do anything, but it provided a fun
52 | little way to show how to import something. Let's actually import
53 | something we can use, like the **math** module:
54 |
55 | ```python
56 | >>> import math
57 | >>> math.sqrt(4)
58 | 2.0
59 | ```
60 |
61 | Here we imported the **math** module and then we did something kind of
62 | new. We called one of its functions, **sqrt** (i.e. square root). To
63 | call a method of an imported module, we have to use the following
64 | syntax: **module\_name.method\_name(argument)**. In this example, we
65 | found the square root of 4. The **math** module has many other functions
66 | that we can use, such as **cos** (cosine), **factorial**, **log**
67 | (logarithm), etc. You can call these functions in much the same way you
68 | did **sqrt**. The only thing you'll need to check is if they accept more
69 | arguments or not. Now let's look at another way to import.
70 |
71 | Using from to import
72 | --------------------
73 |
74 | Some people don't like having to preface everything they type with the
75 | module name. Python has a solution for that! You can actually import
76 | just the functions you want from a module. Let's pretend that we want to
77 | just import the **sqrt** function:
78 |
79 | ```python
80 | >>> from math import sqrt
81 | >>> sqrt(16)
82 | 4.0
83 | ```
84 |
85 | This works pretty much exactly how it is read: **from the math module,
86 | import the sqrt function**. Let me explain it another way. We use
87 | Python's **from** keyword to import the **sqrt** function **from** the
88 | **math** module. You can also use this method to import multiple
89 | functions from the math function:
90 |
91 | ```python
92 | >>> from math import pi, sqrt
93 | ```
94 |
95 | In this example, we import both **pi** and **sqrt**. If you tried to
96 | access **pi** you may have noticed that it's actually a value and not a
97 | function that you can call. It just returns the value of pi. When you do
98 | an import, you may end up importing a value, a function or even another
99 | module! There's one more way to import stuff that we need to cover.
100 | Let's find out how to import everything!
101 |
102 | Importing Everything!
103 | ---------------------
104 |
105 | Python provides a way to import **all** the functions and values from a
106 | module as well. This is actually a **bad** idea as it can contaminate
107 | your **namespace**. A namespace is where all your variables live during
108 | the life of the program. So let's say you have your own variable named
109 | **sqrt**, like this:
110 |
111 | ```python
112 | >>> from math import sqrt
113 | >>> sqrt = 5
114 | ```
115 |
116 | Now you have just changed the **sqrt** function into a variable that
117 | holds the value of 5. This is known as **shadowing**. This becomes
118 | especially tricky when you import everything from a module. Let's take a
119 | look:
120 |
121 | ```python
122 | >>> from math import *
123 | >>> sqrt = 5
124 | >>> sqrt(16)
125 | Traceback (most recent call last):
126 | File "", line 1, in
127 | TypeError: 'int' object is not callable
128 | ```
129 |
130 | To import everything, instead of specifying a list of items, we just use
131 | the "\*" wildcard which means we want to import everything. If we don't
132 | know what's in the **math** module, we won't realize that we've just
133 | clobbered one of the functions we imported. When we try to call the
134 | **sqrt** function after reassigning it to an integer, we find out that
135 | it no longer works.
136 |
137 | Thus it is recommended that in most cases, you should import items from
138 | modules using one of the previous methods mentioned in this chapter.
139 | There are a few exceptions to this rule. Some modules are made to be
140 | imported using the "\*" method. One prominent example is Tkinter, a
141 | toolkit included with Python that allows you to create desktop user
142 | interfaces. The reason that it is supposedly okay to import Tkinter in
143 | this way is that the modules are named so that it is unlikely you would
144 | reuse one yourself.
145 |
146 | Wrapping Up
147 | -----------
148 |
149 | Now you know all about Python imports. There are dozens of modules
150 | included with Python that you can use to give extra functionality to
151 | your programs. You can use the builtin modules to query your OS, get
152 | information from the Windows Registry, set up logging utilities, parse
153 | XML, and much, much more. We will be covering a few of these modules in
154 | Part II of this book.
155 |
156 | In the next chapter, we will be looking at building our own functions. I
157 | think you'll find this next topic to be very helpful.
158 |
--------------------------------------------------------------------------------
/manuscript/images/appendix_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/appendix_1.jpg
--------------------------------------------------------------------------------
/manuscript/images/barcode.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/barcode.jpg
--------------------------------------------------------------------------------
/manuscript/images/bb_config.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/bb_config.jpg
--------------------------------------------------------------------------------
/manuscript/images/call_exit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/call_exit.jpg
--------------------------------------------------------------------------------
/manuscript/images/cx_config.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/cx_config.jpg
--------------------------------------------------------------------------------
/manuscript/images/doctest.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/doctest.jpg
--------------------------------------------------------------------------------
/manuscript/images/doctest_error.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/doctest_error.jpg
--------------------------------------------------------------------------------
/manuscript/images/doctest_from_file.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/doctest_from_file.jpg
--------------------------------------------------------------------------------
/manuscript/images/doctest_from_file_intepreter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/doctest_from_file_intepreter.jpg
--------------------------------------------------------------------------------
/manuscript/images/gui2exe.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/gui2exe.jpg
--------------------------------------------------------------------------------
/manuscript/images/idle_code_colors.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/idle_code_colors.jpg
--------------------------------------------------------------------------------
/manuscript/images/idle_editor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/idle_editor.jpg
--------------------------------------------------------------------------------
/manuscript/images/idle_main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/idle_main.jpg
--------------------------------------------------------------------------------
/manuscript/images/inno_setup_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/inno_setup_1.jpg
--------------------------------------------------------------------------------
/manuscript/images/inno_setup_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/inno_setup_2.jpg
--------------------------------------------------------------------------------
/manuscript/images/inno_setup_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/inno_setup_3.jpg
--------------------------------------------------------------------------------
/manuscript/images/inno_welcome.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/inno_welcome.jpg
--------------------------------------------------------------------------------
/manuscript/images/mousecovertitlejpg_sm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/mousecovertitlejpg_sm.jpg
--------------------------------------------------------------------------------
/manuscript/images/part_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/part_1.jpg
--------------------------------------------------------------------------------
/manuscript/images/part_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/part_2.jpg
--------------------------------------------------------------------------------
/manuscript/images/part_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/part_3.jpg
--------------------------------------------------------------------------------
/manuscript/images/part_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/part_4.jpg
--------------------------------------------------------------------------------
/manuscript/images/part_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/part_5.jpg
--------------------------------------------------------------------------------
/manuscript/images/path_browser.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/path_browser.jpg
--------------------------------------------------------------------------------
/manuscript/images/pdb_step.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/pdb_step.jpg
--------------------------------------------------------------------------------
/manuscript/images/py2exe_output.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/py2exe_output.jpg
--------------------------------------------------------------------------------
/manuscript/images/py2exe_wx.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/py2exe_wx.jpg
--------------------------------------------------------------------------------
/manuscript/images/pyinstaller.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/pyinstaller.jpg
--------------------------------------------------------------------------------
/manuscript/images/sys_argv.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/sys_argv.jpg
--------------------------------------------------------------------------------
/manuscript/images/title_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/title_page.png
--------------------------------------------------------------------------------
/manuscript/images/wheel_creation.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/driscollis/Python-101-Community-Edition/5439b520256ee404840b30736de9a1d265e4e449/manuscript/images/wheel_creation.jpg
--------------------------------------------------------------------------------
/manuscript/part_1_picture.txt:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/manuscript/part_2_picture.txt:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/manuscript/part_3_picture.txt:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/manuscript/part_4_picture.txt:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/manuscript/part_5_picture.txt:
--------------------------------------------------------------------------------
1 | 
2 |
--------------------------------------------------------------------------------
/manuscript/part_i.txt:
--------------------------------------------------------------------------------
1 | Part I - Learning the Basics
2 | ============================
3 |
4 | In Part I, we will learn the basics of the Python programming language.
5 | This section of the book should get you ready to use all the building
6 | blocks of Python so that you will be ready to tackle the following
7 | sections confidently.
8 |
9 | Let's go over what we'll be covering:
10 |
11 | > - IDLE
12 | > - Strings
13 | > - Lists, Dictionaries and Tuples
14 | > - Conditional statements
15 | > - Loops
16 | > - Comprehensions
17 | > - Exception Handling
18 | > - File I/O
19 | > - Importing modules and packages
20 | > - Functions
21 | > - Classes
22 |
23 | The first chapter in this section will familiarize you with Python's
24 | built-in development environment that is known as IDLE. The next couple
25 | of chapters will go over some of Python's types, such as strings, lists,
26 | and dictionaries. After that we'll look at conditional statements in
27 | Python and looping using Python's **for** and **while** loops.
28 |
29 | In the second half of this section, we will go into comprehensions, such
30 | as list and dictionary comprehensions. Then we'll look at Python's
31 | exception handling capabilities and how Python's file operations work.
32 | Next up is learning how to import pre-made modules and packages. The
33 | last two chapters cover Python functions and classes.
34 |
35 | Let's get started!
36 |
--------------------------------------------------------------------------------
/manuscript/part_ii.txt:
--------------------------------------------------------------------------------
1 | Part II - Learning from the Library
2 | ===================================
3 |
4 | In Part II, you will get an abbreviated tour of some of the Python
5 | Standard Library. The reason it's abbreviated is that the Python
6 | Standard Library is HUGE! So this section is to get you acquainted with
7 | using the modules that come with Python. I will be going over the
8 | modules I use the most in my day-to-day job and the modules I've seen
9 | used by my co-workers. I think this mini-tour will prepare you for
10 | digging in on your own.
11 |
12 | Let's take a look at what we'll be covering:
13 |
14 | > - Introspection
15 | > - csv
16 | > - ConfigParser
17 | > - logging
18 | > - os
19 | > - smtplib / email
20 | > - subprocess
21 | > - sys
22 | > - thread / queues
23 | > - time / datetime
24 |
25 | |
26 |
27 | The first chapter in this section will give you a quick tutorial into
28 | Python's **introspection** abilities; basically you'll learn how to make
29 | Python tell you about itself, which sounds kind of weird but is really
30 | quite valuable to know about. Next we'll learn how to use
31 | **ConfigParser**, a neat little module that let's you read and write
32 | config files. After that we'll take a look at **logging**. The **os**
33 | module can do lots of fun things, but we'll try to focus on the ones
34 | that I think you'll find most useful. The **subprocess** allows you to
35 | open other processes.
36 |
37 | You will find the **sys** module allows you to exit a program, get the
38 | Python path, acquire version information, redirect stdout and a whole
39 | lot more. The thread module allows you to create **threads** in your
40 | program. We won't dive too deep into that subject as it can get
41 | confusing pretty quickly. The **time** and **datetime** modules allow
42 | you to manipulate dates and time in Python, which has many applications
43 | when it comes to developing programs.
44 |
45 | Let's get started!
46 |
--------------------------------------------------------------------------------
/manuscript/part_iii.txt:
--------------------------------------------------------------------------------
1 | Part III - Intermediate Odds and Ends
2 | =====================================
3 |
4 | In Part III, you will learn about some Python internals that many would
5 | consider intermediate-level Python. You have graduated from the milk and
6 | you're ready for some meat! In this section, we will take a look at the
7 | following topics:
8 |
9 | > - Debugging
10 | > - Decorators
11 | > - The lambda statement
12 | > - Profiling your code
13 | > - Testing
14 |
15 | The first chapter in this section will introduce you to Python's
16 | debugging module, **pdb** and how to use it to debug your code. The next
17 | chapter is all about decorators. You will learn about how to create them
18 | and about a few of the decorators that are built into Python. For the
19 | third chapter, we will be looking at the lambda statement, which
20 | basically creates a one-line anonymous function. It's a little weird,
21 | but fun! The fourth chapter will cover how you profile your code. This
22 | discipline gives you the ability to find possible bottlenecks in your
23 | code so that you know where to focus to optimize your code. The final
24 | chapter in this section is about testing your code. In it you will
25 | discover how to test your code using a couple of Python's own built-in
26 | modules.
27 |
28 | I think you will find this section very helpful in continuing your
29 | Python education. Let's jump right in!
30 |
--------------------------------------------------------------------------------
/manuscript/part_iv.txt:
--------------------------------------------------------------------------------
1 | Part IV - Tips, Tricks and Tutorials
2 | ====================================
3 |
4 | In Part IV, you will learn how to install 3rd party packages from the
5 | Python Package Index (PyPI). You will learn a bit about
6 | **easy\_install**, **pip** and **setup.py** and how to use these tools
7 | to install the packages. This is just the first chapter though. Here's a
8 | listing of the packages you will learn about:
9 |
10 | > - configobj - working with Config files in a more "Pythonic" way.
11 | > - lxml - a package for working with XML
12 | > - pylint / pyflakes - Python code analyzers
13 | > - requests - a Python-friendly version of urllib
14 | > - SQLAlchemy - an Object Relational Mapper for Python
15 | > - virtualenv - learn about virtual environments in Python
16 |
17 | The reason we will be looking at **configobj** is because I think it
18 | works better than ConfigParser, the module that comes with Python. The
19 | configobj package has an interface that is just more intuitive and
20 | powerful than ConfigParser. In the next chapter, we'll look at the
21 | **lxml** module and learn a couple of new ways to read, parse and create
22 | XML. In the fourth chapter, we will look at **pylint** and **pyflakes**,
23 | which are great for code analysis. They can look at your module and
24 | check for errors. pylint can also be used to help you get your code to
25 | conform to PEP8, the Python style guide.
26 |
27 | The **requests** package is great replacement for the **urllib** module.
28 | Its interface is simpler and the documentation is quite good. SQLAlchemy
29 | is the premier Object Relational Mapper for Python. It allows you to
30 | write SQL queries, tables, etc in Python code. One of its best features
31 | is that if you need to switch database backends, you won't have to
32 | change your code very much to continue working with said database. For
33 | the last chapter, we'll look at **virtualenv**, a neat module that
34 | allows you to create mini-virtual environments that you can write your
35 | code in. These virtual environments are especially handy for testing out
36 | new modules or just new releases of modules before you apply them to
37 | your Python core installation.
38 |
--------------------------------------------------------------------------------
/manuscript/part_v.txt:
--------------------------------------------------------------------------------
1 | Part V - Packaging and Distribution
2 | ===================================
3 |
4 | In Part V you will learn about Python packaging and the various methods
5 | to distribute your code. You will learn about the following:
6 |
7 | > - How to create a module and package
8 | > - Publishing your Packages to the Python Packaging Index (PyPI)
9 | > - Python eggs
10 | > - Python wheels
11 | > - py2exe
12 | > - bb\_freeze
13 | > - cx\_Freeze
14 | > - PyInstaller
15 | > - GUI2Exe
16 | > - How to Create an Installer with InnoSetup
17 |
18 | The first chapter of this section describes how to create a module or
19 | package. Then in the following chapter, we will go over publishing our
20 | package to PyPI. Next up, we will learn how to create and install a
21 | Python egg and the Python wheel.
22 |
23 | The next four chapters will cover how to create binaries using the
24 | following 3rd party packages: py2exe, bb\_freeze, cx\_Freeze and
25 | PyInstaller. The only package in this list that is actually compatible
26 | with Python 3 is cx\_Freeze. Because of this fact, we will be showing
27 | Python 2 examples in these four chapters so that we can easily compare
28 | all 4 packages and their capabilities.
29 |
30 | The next to last chapter will show you how to use GUI2Exe, a neat little
31 | user interface that was created to go on top of py2exe, bb\_freeze, etc.
32 | GUI2Exe makes creating binaries even easier!
33 |
34 | The last chapter of this section will show how to create an installer
35 | using InnoSetup. Let's get started!
36 |
--------------------------------------------------------------------------------