├── .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 | ![image](images/wheel_creation.jpg) 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 | ![image](images/part_1.jpg) 2 | -------------------------------------------------------------------------------- /manuscript/part_2_picture.txt: -------------------------------------------------------------------------------- 1 | ![image](images/part_2.jpg) 2 | -------------------------------------------------------------------------------- /manuscript/part_3_picture.txt: -------------------------------------------------------------------------------- 1 | ![image](images/part_3.jpg) 2 | -------------------------------------------------------------------------------- /manuscript/part_4_picture.txt: -------------------------------------------------------------------------------- 1 | ![image](images/part_4.jpg) 2 | -------------------------------------------------------------------------------- /manuscript/part_5_picture.txt: -------------------------------------------------------------------------------- 1 | ![image](images/part_5.jpg) 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 | --------------------------------------------------------------------------------