📄 Page
1
(This page has no text content)
📄 Page
2
IMPRACTICAL PYTHON PROJECTS Playful Programming Activities to Make You Smarter by Lee Vaughan San Francisco History Topics Tutorials Offers & Deals Highlights Settings Support Sign Out
📄 Page
3
IMPRACTICAL PYTHON PROJECTS. Copyright © 2019 by Lee Vaughan. All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. ISBN10: 159327890X ISBN13: 9781593278908 Publisher: William Pollock Production Editor: Janelle Ludowise Cover Illustration: Josh Ellingson Interior Design: Octopod Studios Developmental Editor: Zach Lebowski Technical Reviewers: Jeremy Kun, Michael Contraveos, and Michele Pratusevich Copyeditor: Rachel Monaghan Compositor: David Van Ness Proofreader: Paula L. Fleming Indexer: Beth NaumanMontana The following images are reproduced with permission: Figure 41 courtesy of the Library of Congress; Figure 71 created by vecteezy.com; rat silhouette in Figure 72 created by vecteezy.com; door image in Figures 111, 113, 114, 115, and 116 created by Dooder at Freepik.com; goat and moneybag images in Figures 111, 114, 115, and 116 created by Freepik.com; Figures 101, 107, 131, 1421, and 151 from NASA; satellite images in Figures 1413 and 1424 courtesy of www.ahasoft.com/; output in Figure 125 supplied by ifa.com For information on distribution, translations, or bulk sales, please contact No Starch Press, Inc. directly: No Starch Press, Inc. 245 8th Street, San Francisco, CA 94103 phone: 1.415.863.9900; info@nostarch.com www.nostarch.com Playlists History Topics Tutorials Offers & Deals Highlights Settings Support Sign Out
📄 Page
4
Library of Congress CataloginginPublication Data Names: Vaughan, Lee, author. Title: Impractical Python projects : playful programming activities to make you smarter / Lee Vaughan. Description: First edition. | San Francisco : No Starch Press, Inc., [2019] | Includes bibliographical references and index. Identifiers: LCCN 2018027576 (print) | LCCN 2018029119 (ebook) | ISBN 9781593278915 (epub) | ISBN 1593278918 (epub) | ISBN 9781593278908 (pbk. : alk. paper) | ISBN 159327890X (pbk. : alk. paper) Subjects: LCSH: Python (Computer program language) Classification: LCC QA76.73.P98 (ebook) | LCC QA76.73.P98 V38 2019 (print) | DDC 005.13/3dc23 LC record available at https://lccn.loc.gov/2018027576 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it.
📄 Page
5
INTRODUCTION Welcome to Impractical Python Projects! Here, you’ll use the Python programming language to explore Mars, Jupiter, and the farthest reaches of the galaxy; the souls of poets; the world of high finance; the underworld of espionage and vote tampering; the trickery of game shows; and more. You’ll use techniques such as Markov chain analysis to write haiku, Monte Carlo simulation to model financial markets, image stacking to improve your astrophotography, and genetic algorithms to breed an army of gigantic rats, all while gaining experience with modules like pygame, Pylint, pydocstyle, tkinter, python-docx, matplotlib, and pillow. And most of all, you’ll have fun. WHO THIS BOOK IS FOR You can think of this as your second Python book. It’s designed to follow and complement either a complete beginner’s book or an introductory class. You’ll be able to continue selftraining using a projectbased approach, without wasting your money or shelf space on a thorough rehashing of concepts you’ve already learned. But don’t worry, I won’t leave you hanging; all the code is annotated and explained. These projects are for anyone who wants to use programming to conduct experiments, test theories, simulate nature, or just have fun. This includes people who use programming as part of their jobs (like scientists and engineers) but who aren’t programmers per se, as well as those I call the “determined nonspecialists”— dilettantes and dabblers who enjoy programming problems as a fun pastime. If you’ve wanted to toy with the concepts presented here but found starting potentially y History Topics Tutorials Offers & Deals Highlights Settings Sup rt Sign Out
📄 Page
6
complicated projects from scratch too daunting or timeconsuming, this book is for you. WHAT’S IN THIS BOOK As you work through the projects, you’ll increase your knowledge of useful Python libraries and modules; learn more shortcuts, builtin functions, and helpful techniques; and practice designing, testing, and optimizing programs. Additionally, you’ll be able to relate what you’re doing to realworld applications, datasets, and issues. To quote Ralph Waldo Emerson, “Nothing great was ever achieved without enthusiasm.” This includes the learning experience. The ultimate goal of this book is to spark your imagination and lead you to develop interesting projects of your own. Don’t worry if they seem too ambitious at first; a little diligence and a lot of googling can work miracles—and faster than you think. The following is an overview of the chapters in this book. You don’t have to work through them sequentially, but the easiest projects are at the beginning, and I explain new concepts, modules, and techniques more thoroughly when they’re first introduced. Chapter 1: Silly Name Generator This warmup project introduces the Python PEP 8 and PEP 257 style guides as well as the Pylint and pydocstyle modules, which analyze your code’s conformance to these guidelines. The end product is a goofyname generator inspired by the USA Network TV show Psych. Chapter 2: Finding Palingram Spells Learn how to profile your code while saving DC Comics sorceress Zatanna from a painful death. Search online dictionaries for the magical palingrams that Zatanna needs to beat a timereversing villain. Chapter 3: Solving Anagrams Write a program that helps a user create a phrase anagram from their name; for example, Clint Eastwood yields old west action. Then help Tom Marvolo Riddle derive his anagram, “I am Lord Voldemort,” using linguistic sieves. Chapter 4: Decoding American Civil War Ciphers Investigate and crack one of the most successful military ciphers in history, the Union route cipher. Then help spies on both sides send and decode secret messages using the zigzagging rail fence cipher. Chapter 5: Encoding English Civil War Ciphers Read a message hidden in plain sight by decoding a null cipher from the English Civil War. Then save the head of Mary, Queen of Scots, by designing and implementing code to accomplish the more difficult
📄 Page
7
task of writing a null cipher. Chapter 6: Writing in Invisible Ink Help a corporate mole betray Sherlock Holmes’s dad and evade detection with invisible electronic ink. This chapter is based on an episode of the CBS television show Elementary. Chapter 7: Breeding Giant Rats with Genetic Algorithms Use genetic algorithms—inspired by Darwinian evolution—to breed a race of superrats the size of female bullmastiffs. Then help James Bond crack a safe with 10 billion possible combinations in the blink of an eye. Chapter 8: Counting Syllables for Haiku Poetry Teach your computer to count syllables in English as a prelude to writing Japanese poetry, or haiku, in the next chapter. Chapter 9: Writing Haiku with Markov Chain Analysis Teach your computer to write haiku by combining the syllablecounting module from Chapter 8 with Markov chain analysis and a training corpus of several hundred ancient and modern haiku. Chapter 10: Are We Alone? Exploring the Fermi Paradox Investigate the absence of alien radio signals using Drake’s equation, the dimensions of the Milky Way galaxy, and assumptions about the size of detectable “emissions bubbles.” Learn and use the popular tkinter module to build a graphical display of the galaxy and Earth’s own radio bubble. Chapter 11: The Monty Hall Problem Help the world’s smartest woman win the Monty Hall problem argument. Then use objectoriented programming (OOP) to build a version of Monty’s famous game with a fun graphical interface. Chapter 12: Securing Your Nest Egg Plan your (or your parents’) secure retirement using a Monte Carlo–based financial simulation. Chapter 13: Simulating an Alien Volcano Use pygame to simulate a volcanic eruption on Io, one of Jupiter's moons. Chapter 14: Mapping Mars with the Mars Orbiter Build a gravitybased arcade game and nudge a satellite into a circular mapping orbit without running out of fuel or burning up in the atmosphere. Display readouts of key parameters, track orbital paths, add the planet’s shadow, and spin Mars slowly on its axis, all while learning orbital mechanics!
📄 Page
8
Chapter 15: Improving Your Astrophotography with Planet Stacking Reveal Jupiter’s cloud bands and Great Red Spot by optically stacking poorquality video images using the Python imaging library. Learn how to work with files, folders, and directory paths using the builtin os and shutil modules. Chapter 16: Finding Frauds with Benford’s Law Use Benford’s law to investigate vote tampering in the 2016 presidential election. Use matplotlib to summarize the results in a chart. Each chapter ends with at least one Practice Project or Challenge Project. Each Practice Project comes with a solution. That doesn’t mean it’s the best solution—you may come up with a better one on your own, so don’t peek ahead! With the Challenge Projects, however, you’re truly on your own. When Cortez invaded Mexico in 1519, he burned his caravels so that his conquistadors would realize there was no going back; they would have to face the Aztecs with grim and unwavering determination. Thus, the expression “burn your boats” has come to represent wholeheartedness or full commitment to a task. This is how you should face the Challenge Projects—as if your boat were burned—and if you do, you’re likely to learn more from these exercises than from any other part of the book! Python Version, Platform, and IDE I constructed each of the projects in this book with Python v3.5 in a Microsoft Windows 10 environment. If you’re using a different operating system, no problem: I suggest compatible modules for other platforms, where appropriate. The code examples and screen captures in this book are from either the Python IDLE text editor or the interactive shell. IDLE stands for integrated development and learning environment. It’s an integrated development environment (IDE) with an L added so that the acronym references Eric Idle of Monty Python fame. The interactive shell, also called the interpreter, is a window that lets you immediately execute commands and test code without needing to create a file. IDLE has numerous drawbacks, such as the lack of a linenumber column, but it is free and bundled with Python, so everyone has access to it. You are welcome to use whichever IDE you wish. There are many choices available online, such as Geany (pronounced genie), PyCharm, and PyScripter. Geany works with a wide range of operating systems, including Unix, macOS, and Windows. PyCharm works with Linux, Windows, and macOS. PyScripter works with Windows. For an extensive listing of available Python development tools and compatible platforms, visit
📄 Page
9
https://wiki.python.org/moin/DevelopmentTools/. The Code Every line of code is provided for each project in this book, and I recommend you enter it by hand whenever possible. A college professor once told me that we “learn through our hands,” and I have to agree that keying in code forces you to pay maximum attention to what’s going on. But if you want to complete a project quickly or you accidentally delete all your work, you can download all of the code, including solutions to the Practice Projects, from https://www.nostarch.com/impracticalpython/. Coding Style This book is about problem solving and beginnerlevel fun, so the code may deviate at times from best practices and peak efficiency. Occasionally, you may use list comprehension or a special operator, but for the most part, you’ll focus on simple, approachable code that’s easy to learn. Keeping things simple is important for the programming nonprogrammers who read this book. Much of their code may be “Kleenex code”—used once or twice for a specific purpose and then thrown away. This is the type of code that might be shared with colleagues, or thrust upon them during staff changes, so it should be easy to pick up and understand. All of the main project code is annotated and explained in a standalone manner, and it generally follows the style recommendations from Python Enhancement Proposal 8, otherwise known as PEP 8. Details on PEP 8, and software to help you honor these guidelines, are in Chapter 1. WHERE TO GET HELP Taking on a programming challenge can be, well, challenging. Coding isn’t always something that you can intuitively figure out—even with a language as friendly as Python. Throughout the following chapters, I will provide links and references to useful sources of information, but for projects you formulate on your own, nothing can beat online searches. The key to successful searching is knowing what to ask. This can be quite frustrating at first, but think of it as a game of Twenty Questions. Keep honing your keywords with
📄 Page
10
each successive search until you find an answer or reach a point of diminishing returns. If books and online searches fail, then the next step is to ask someone. You can do this online, either for a fee or at free forums like Stack Overflow (https://stackoverflow.com/). But be warned: the members of these sites don’t suffer fools gladly. Be sure to read their “How do I ask a good question?” pages before posting; for example, you can find the one for Stack Overflow at http://stackoverflow.com/help/howtoask/. ONWARD! Thanks for taking the time to read the Introduction! You clearly want to get as much as possible from this book, and you’re off to a good start. When you reach the other end, you’ll be more adept at Python and better prepared to solve challenging realworld problems. Let’s get to work.
📄 Page
11
1 SILLY NAME GENERATOR The USA Network television channel once ran a detective dramedy called Psych, in which hyperobservant amateur sleuth Sean Spencer solved cases while pretending to use psychic abilities. A trademark of the show was the way he would introduce his sidekick, Gus, with goofy names made up on the fly, like Galileo Humpkins, Lavender Gooms, and Bad News Marvin Barnes. This made an impression on me because, years ago, someone who worked at the Census Bureau gave me a list of real names every bit as strange as those invented by Sean. PROJECT #1: GENERATING PSEUDONYMS In this warmup project, you’ll write a simple Python program that generates nutty names by randomly combining first names and surnames. With any luck, you’ll produce a plethora of aliases that would make any sidekick proud. You’ll also review best practice coding guidelines and apply external programs that will help you write code that conforms to those guidelines. Psych not your thing? Replace the names in my list in the code with your own jokes or theme. You could just as easily turn this project into a Game of Thrones name generator, or perhaps you want to discover your very own “Benedict Cumberbatch” name; my favorite is Bendylick Cricketbat. History Topics Tutorials Offers & Deals Highlights Settings Support Sign Out
📄 Page
12
THE OBJECTIVE Randomly generate funny sidekick names using Python code that conforms to established style guidelines. PLANNING AND DESIGNING A PROJECT Planning time is never wasted time. It doesn’t matter whether you’re programming for fun or profit; at some point, you’ll need to estimate—fairly accurately—how long the project will take, what obstacles you may encounter, and what tools and resources you’ll need to do the work. And to accomplish that, you’ll need to know what you’re trying to create in the first place! A successful manager once told me that his secret was simply to ask lots of questions: What are you trying to do? Why are you doing it? Why are you doing it this way? How much time do you have? How much money? Answering these questions is extremely helpful to the design process and gives you a clear line of sight. In his book Think Python, 2nd Edition (O’Reilly, 2015), Allen Downey describes two types of software development plans: “prototype and patch” and “designed development.” With prototype and patch, you start with a simple program and then use patches, or edited code, to handle problems encountered in testing. This can be a good approach when you’re working through a complex problem you don’t understand very well. But it can also produce complicated and unreliable code. If you have a clear view of the problem and how you want to solve it, you should use a designed development plan to avoid future issues and their subsequent patches. This approach can make coding easier and more efficient, and it typically leads to stronger and more reliable code. For all the projects in this book, you’ll start with a clearly defined problem or goal that will form the basis of your design decisions. Then we’ll discuss strategy to better understand the issues and create a designed development plan. The Strategy You’ll start with two lists—first and last—of funny names. The lists will be relatively short, so they won’t be memory intensive, won’t need to be dynamically updated, and shouldn’t present any runtime issues. Since all you’ll need to do is read names from the list, you’ll use a tuple as a container.
📄 Page
13
With your two tuples of names, you’ll generate new names—pairing a first name with a last—at the touch of a button. That way, the user can easily repeat the process until a sufficiently funny name appears. You should also highlight the name in the interpreter window somehow so it stands out from the command prompts. The IDLE shell doesn’t provide many font options, but you probably know—all too well—that errors appear in red. The default for the print() function is the standard output, but with the sys module loaded, you can redirect the output to the error channel, with its trademark red coloring, using the file parameter: print(something, file=sys.stderr). Finally, you’ll determine what style recommendations exist for Python programming. These guidelines should address not only the code but also documentation embedded within the code. The Pseudocode “You can always count on the Americans to do the right thing after they have tried everything else.” That quote, weakly linked to Winston Churchill, sums up the way many people approach writing pseudocode. Pseudocode is a highlevel, informal way to describe computer programs using structured English or any human language. It should resemble a simplified programming language and include keywords and proper indentations. Developers use it to ignore all the arcane syntax of true programming languages and focus on the underlying logic. Despite its widespread use, pseudocode has no official standards— only guidelines. If you find you’ve hacked your way into frustration, it may be because you didn’t take the time to write pseudocode. I am a true believer in it, as pseudocode has—without fail —guided me to solutions when I was otherwise lost in the woods. Consequently, you’ll use some form of pseudocode in most of the projects in this book. At the very least, I hope you’ll see its utility, but I also hope you’ll develop the discipline to write it in your own projects. A very highlevel pseudocode for our funny name generator could look like this: Load a list of first names Load a list of surnames Choose a first name at random
📄 Page
14
Assign the name to a variable Choose a surname at random Assign the name to a variable Print the names to the screen in order and in red font Ask the user to quit or play again If user plays again: repeat If user quits: end and exit Unless you’re trying to pass a programming class or provide clear instructions to others, focus on the purpose of the pseudocode; don’t worry about slavishly complying with the (nonstandard) guidelines for writing it. And don’t stop with programming— you can apply the pseudocode process to much more. Once you get the hang of it, you might find it helps you complete other tasks like doing your taxes, planning your investments, building a house, or getting ready for a camping trip. It’s a great way to focus your thinking and carry programming successes over into real life. If only Congress would use it! THE CODE Listing 11 is the code for the funny name generator, pseudonyms.py, which compiles and prints a list of pseudonyms from two tuples of names. If you don’t want to type all the names, you can type a subset or download the code from https://nostarch.com/impracticalpython/. pseudonyms.py ➊ import sys, random ➋ print("Welcome to the Psych 'Sidekick Name Picker.'\n") print("A name just like Sean would pick for Gus:\n\n") first = ('Baby Oil', 'Bad News', 'Big Burps', "Bill 'BeenieWeenie'", "Bob 'Stinkbug'", 'Bowel Noises', 'Boxelder', "Bud 'Lite' ", 'Butterbean', 'Buttermilk', 'Buttocks', 'Chad', 'Chesterfield', 'Chewy', 'Chigger", "Cinnabuns', 'Cleet', 'Cornbread', 'Crab Meat', 'Crapps', 'Dark Skies', 'Dennis Clawhammer', 'Dicman', 'Elphonso', 'Fancypants', 'Figgs', 'Foncy', 'Gootsy', 'Greasy Jim', 'Huckleberry',
📄 Page
15
'Huggy', 'Ignatious', 'Jimbo', "Joe 'Pottin Soil'", 'Johnny', 'Lemongrass', 'Lil Debil', 'Longbranch', '"Lunch Money"', 'Mergatroid', '"Mr Peabody"', 'OilCan', 'Oinks', 'Old Scratch', 'Ovaltine', 'Pennywhistle', 'Pitchfork Ben', 'Potato Bug', 'Pushmeet','Rock Candy', 'Schlomo', 'Scratchensniff', 'Scut', "Sid 'The Squirts'", 'Skidmark', 'Slaps', 'Snakes', 'Snoobs', 'Snorki', 'Soupcan Sam', 'Spitzitout', 'Squids', 'Stinky', 'Storyboard', 'Sweet Tea', 'TeeTee', 'Wheezy Joe', "Winston 'Jazz Hands'", 'Worms') last = ('Appleyard', 'Bigmeat', 'Bloominshine', 'Boogerbottom', 'Breedslovetrout', 'Butterbaugh', 'Clovenhoof', 'Clutterbuck', 'Cocktoasten', 'Endicott', 'Fewhairs', 'Gooberdapple', 'Goodensmith', 'Goodpasture', 'Guster', 'Henderson', 'Hooperbag', 'Hoosenater', 'Hootkins', 'Jefferson', 'Jenkins', 'JingleySchmidt', 'Johnson', 'Kingfish', 'Listenbee', "M'Bembo", 'McFadden', 'Moonshine', 'Nettles', 'Noseworthy', 'Olivetti', 'Outerbridge', 'Overpeck', 'Overturf', 'Oxhandler', 'Pealike', 'Pennywhistle', 'Peterson', 'Pieplow', 'Pinkerton', 'Porkins', 'Putney', 'Quakenbush', 'Rainwater', 'Rosenthal', 'Rubbins', 'Sackrider', 'Snuggleshine', 'Splern', 'Stevens', 'Stroganoff', 'SugarGold', 'Swackhamer', 'Tippins', 'Turnipseed', 'Vinaigrette', 'Walkingstick', 'Wallbanger', 'Weewax', 'Weiners', 'Whipkey', 'Wigglesworth', 'Wimplesnatch', 'Winterkorn', 'Woolysocks') ➌ while True: ➍ firstName = random.choice(first) ➎ lastName = random.choice(last) print("\n\n") ➏ print("{} {}".format(firstName, lastName), file=sys.stderr) print("\n\n") ➐ try_again = input("\n\nTry again? (Press Enter else n to quit)\n ") if try_again.lower() == "n": break ➑ input("\nPress Enter to exit.")
📄 Page
16
Listing 11: Generates silly pseudonyms from tuples of names First, import the sys and random modules ➊. You’ll use sys to access the systemspecific error message functionality, so you can color your output an eyecatching red in the IDLE window. And random lets you pick, at random, items from your name lists. The print statements at ➋ introduce the program to the user. The newline command \n forces a new line, and single quotes '' allow you to use quotes in the printout without having to resort to the backslash escape character, which would reduce code readability. Next, define your tuples of names. Then initiate the while loop ➌. Setting while = True basically means “Keep running until I tell you to stop.” Eventually, you’ll use a break statement to end the loop. The loop starts by choosing a name from the first tuple at random and then assigns that name to the variable firstName ➍. It uses the random module’s choice method to return a random element from a nonempty sequence—in this case, the tuple of first names. Next, choose a surname at random from the last tuple and assign it to the variable lastName ➎. Now that you have both names, print them and trick IDLE into using the red “error” font by supplying the optional argument file=sys.stderr to the print statement ➏. Use the newer string format method, rather than the older string format operator (%), to convert the name variables to a string. To read more about the new method, see https://docs.python.org/3.7/library/string.html. Once the name is displayed, ask the user to choose to play again or quit, using input to provide the instruction in quotes. In this case, include a few blank lines as well to make the funny name more obvious in the IDLE window. If the user responds by pressing the ENTER key, nothing is returned to the try_again variable ➐. With nothing returned, the condition on the if statement isn’t met, the while loop continues, and a new name is printed. If the user instead presses the N key, the if statement results in a break command, and the loop ends because the while statement no longer evaluates to True. Use the lowercase string method .lower() to mitigate the player’s CAPS LOCK key being engaged. In other words, it doesn’t matter whether the user inputs a lowercase or uppercase N, because the program will always read it as lowercase. Finally, ask the user to exit by pressing the ENTER key ➑. Pressing ENTER doesn’t assign the return value of input() to a variable, the program ends, and the console window closes. Pressing F5 in the IDLE editor window executes the completed
📄 Page
17
program. This code works, but working isn’t enough—programs in Python should work with style. Using the Python Community’s Style Guide According to the Zen of Python (https://www.python.org/dev/peps/pep0020/), “There should be one—and preferably only one—obvious way to do something.” In the spirit of providing a single obvious “right way” of doing things and building consensus around these practices, the Python community releases Python Enhancement Proposals, which are coding conventions for the Python code comprising the standard library in the main Python distribution. The most important of these is PEP 8, a style guide for Python programming. PEP 8 evolves over time as new conventions are identified and past ones are rendered obsolete by changes in the language. PEP 8 (https://www.python.org/dev/peps/pep0008/) sets standards for naming conventions; use of blank lines, tabs, and spaces; maximum line length; comments; and so on. The goal is to improve the readability of code and make it consistent across a wide spectrum of Python programs. When you start programming, you should strive to learn and follow the accepted conventions, before bad habits become engrained. The code in this book will conform closely to PEP 8, but I have overridden some conventions (by using less commented code, fewer blank lines, and shorter docstrings, for example) in deference to the publishing industry. Standardized names and procedures are especially important when you’re working in crossfunctional teams. A lot can get lost in translation between scientists and engineers, as in 1999, when engineers lost the Mars Climate Orbiter because different teams used different measurement units. For almost two decades, I built computer models of the earth that were transferred to an engineering function. The engineers used scripts to load these models into their own proprietary software. They would share these scripts among projects for efficiency and to help the inexperienced. Since these “command files” were customized to each project, the engineers were understandably annoyed when attribute names changed during model updates. In fact, one of their internal guidelines was “Beg, bribe, or bully your modeler into using consistent property names!” Checking Your Code with Pylint You should become familiar with PEP 8, but you’ll still make mistakes, and comparing your code to the guide is a major drag. Luckily, programs such as Pylint, pycodestyle,
📄 Page
18
and Flake8 can help you easily follow the PEP 8 style recommendations. For this project, you’ll use Pylint. Installing Pylint Pylint is a source code, bug, and quality checker for the Python programming language. To download a free copy, go to https://www.pylint.org/#install and find the install button for your platform. This button will show the command for installing Pylint. For example, in Windows, go to the folder that contains your copy of Python (such as C:\Python35), use SHIFTrightclick to open a context menu, and then click either open command window here or open PowerShell window here, depending on which version of Windows you’re using. In the window, run pip install pylint. Running Pylint In Windows, Pylint is run from a command window or, for newer systems, the PowerShell (you open both by using SHIFTrightclick in the folder containing the Python module you want to check). Type pylint filename to run the program (see Figure 11). The .py extension is optional, and your directory path will vary from the one shown. On macOS or another Unixbased system, use the terminal emulator. Figure 11: The Windows command window with the command to run Pylint The command window will display the Pylint results. Here’s a sample of a useful output: C:\Python35\Python 3 Stuff\Psych>pylint pseudonyms.py No config file found, using default configuration ************* Module pseudonyms C: 45, 0: No space allowed around keyword argument assignment print(firstName, lastName, file = sys.stderr) ^ (badwhitespace) C: 1, 0: Missing module docstring (missingdocstring) C: 2, 0: Multiple imports on one line (sys, random) (multipleimports) C: 7, 0: Invalid constant name "first" (invalidname)
📄 Page
19
C: 23, 0: Invalid constant name "last" (invalidname) C: 40, 4: Invalid constant name "firstName" (invalidname) C: 42, 4: Invalid constant name "lastName" (invalidname) C: 48, 4: Invalid constant name "try_again" (invalidname) The capital letter at the start of each line is a message code. For example, C: 15, 0 refers to a coding standard violation in line 15, column 0. You can reference the following key for the various Pylint message codes: R Refactor for a “good practice” metric violation C Convention for coding standard violation W Warning for stylistic problems or minor programming issues E Error for important programming issues (i.e., most probably a bug) F Fatal for errors that prevent further processing Pylint will end its report by grading your program’s conformance to PEP 8. In this case, your code received a 4 out of 10: Global evaluation Your code has been rated at 4.00/10 (previous run: 4.00/10, +0.00) Handling False Constant Name Errors You might have noticed that Pylint incorrectly assumes all variable names in the global space refer to constants, and should therefore be in all caps. You can work around this shortcoming in a number of ways. The first is to embed your code in a main() function (as shown in Listing 12); that way, it’s out of the global space. def main(): some indented code some indented code some indented code ➊ if __name__ == "__main__": ➋ main()
📄 Page
20
Listing 12: Defines and calls a main() function The __name__ variable is a special builtin variable that you can use to evaluate whether a program is being run in standalone mode or as an imported module; remember that a module is just a Python program used inside of another Python program. If you run the program directly, __name__ is set to __main__. In Listing 12 __name__ is used to ensure that, when the program is imported, the main() function isn’t run until you intentionally call it, but when you run the program directly, the condition in the if statement is met ➊ and main() is automatically called ➋. You don’t always need this convention. For example, if your code just defines a function, you can load it as a module and call it without the need for __name__. Let’s embed everything in pseudonyms.py, except for the import statement, under a main() function and then embed the main() function call under an if statement, as in Listing 12. You can make the changes yourself or download the pseudonyms_main.py program from the website. Rerun Pylint. You should get the following results in your command window. C:\Python35\Python 3 Stuff\Psych>pylint pseudonyms_main No config file found, using default configuration ************* Module pseudonyms_main C: 47, 0: No space allowed around keyword argument assignment print(firstName, lastName, file = sys.stderr) ^ (badwhitespace) C: 1, 0: Missing module docstring (missingdocstring) C: 2, 0: Multiple imports on one line (sys, random) (multipleimports) C: 4, 0: Missing function docstring (missingdocstring) C: 42, 8: Invalid variable name "firstName" (invalidname) C: 44, 8: Invalid variable name "lastName" (invalidname) Now those annoying comments about invalid constant names have disappeared, but you aren’t out of the woods yet. As much as I like them, Python conventions don’t allow for camel case names, like firstName. Configuring Pylint When evaluating small scripts, I prefer to use the Pylint defaults and ignore the false “constant name” errors. I also like to run the option -rn (short for -reports=n) to suppress the large volume of extraneous statistics that Pylint returns: