Automate the Boring Stuff with Python

Home > Other > Automate the Boring Stuff with Python > Page 40
Automate the Boring Stuff with Python Page 40

by Al Sweigart


  import textmyself textmyself.textmyself('The boring task is finished.')

  You need to sign up for Twilio and write the texting code only once. After that, it’s just two lines of code to send a text from any of your other programs.

  Summary

  We communicate with each other on the Internet and over cell phone networks in dozens of different ways, but email and texting predominate. Your programs can communicate through these channels, which gives them powerful new notification features. You can even write programs running on different computers that communicate with one another directly via email, with one program sending emails with SMTP and the other retrieving them with IMAP.

  Python’s smtplib provides functions for using the SMTP to send emails through your email provider’s SMTP server. Likewise, the third-party imapclient and pyzmail modules let you access IMAP servers and retrieve emails sent to you. Although IMAP is a bit more involved than SMTP, it’s also quite powerful and allows you to search for particular emails, download them, and parse them to extract the subject and body as string values.

  Texting is a bit different from email, since, unlike email, more than just an Internet connection is needed to send SMS texts. Fortunately, services such as Twilio provide modules to allow you to send text messages from your programs. Once you go through an initial setup process, you’ll be able to send texts with just a couple lines of code.

  With these modules in your skill set, you’ll be able to program the specific conditions under which your programs should send notifications or reminders. Now your programs will have reach far beyond the computer they’re running on!

  Practice Questions

  Q:

  1. What is the protocol for sending email? For checking and receiving email?

  Q:

  2. What four smtplib functions/methods must you call to log in to an SMTP server?

  Q:

  3. What two imapclient functions/methods must you call to log in to an IMAP server?

  Q:

  4. What kind of argument do you pass to imapObj.search()?

  Q:

  5. What do you do if your code gets an error message that says got more than 10000 bytes?

  Q:

  6. The imapclient module handles connecting to an IMAP server and finding emails. What is one module that handles reading the emails that imapclient collects?

  Q:

  7. What three pieces of information do you need from Twilio before you can send text messages?

  Practice Projects

  For practice, write programs that do the following.

  Random Chore Assignment Emailer

  Write a program that takes a list of people’s email addresses and a list of chores that need to be done and randomly assigns chores to people. Email each person their assigned chores. If you’re feeling ambitious, keep a record of each person’s previously assigned chores so that you can make sure the program avoids assigning anyone the same chore they did last time. For another possible feature, schedule the program to run once a week automatically.

  Here’s a hint: If you pass a list to the random.choice() function, it will return a randomly selected item from the list. Part of your code could look like this:

  chores = ['dishes', 'bathroom', 'vacuum', 'walk dog'] randomChore = random.choice(chores) chores.remove(randomChore) # this chore is now taken, so remove it

  Umbrella Reminder

  Chapter 11 showed you how to use the requests module to scrape data from http://weather.gov/. Write a program that runs just before you wake up in the morning and checks whether it’s raining that day. If so, have the program text you a reminder to pack an umbrella before leaving the house.

  Auto Unsubscriber

  Write a program that scans through your email account, finds all the unsubscribe links in all your emails, and automatically opens them in a browser. This program will have to log in to your email provider’s IMAP server and download all of your emails. You can use BeautifulSoup (covered in Chapter 11) to check for any instance where the word unsubscribe occurs within an HTML link tag.

  Once you have a list of these URLs, you can use webbrowser.open() to automatically open all of these links in a browser.

  You’ll still have to manually go through and complete any additional steps to unsubscribe yourself from these lists. In most cases, this involves clicking a link to confirm.

  But this script saves you from having to go through all of your emails looking for unsubscribe links. You can then pass this script along to your friends so they can run it on their email accounts. (Just make sure your email password isn’t hardcoded in the source code!)

  Controlling Your Computer Through Email

  Write a program that checks an email account every 15 minutes for any instructions you email it and executes those instructions automatically. For example, BitTorrent is a peer-to-peer downloading system. Using free BitTorrent software such as qBittorrent, you can download large media files on your home computer. If you email the program a (completely legal, not at all piratical) BitTorrent link, the program will eventually check its email, find this message, extract the link, and then launch qBittorrent to start downloading the file. This way, you can have your home computer begin downloads while you’re away, and the (completely legal, not at all piratical) download can be finished by the time you return home.

  Chapter 15 covers how to launch programs on your computer using the subprocess.Popen() function. For example, the following call would launch the qBittorrent program, along with a torrent file:

  qbProcess = subprocess.Popen(['C:\Program Files (x86)\qBittorrent\ qbittorrent.exe', 'shakespeare_complete_works.torrent'])

  Of course, you’ll want the program to make sure the emails come from you. In particular, you might want to require that the emails contain a password, since it is fairly trivial for hackers to fake a “from” address in emails. The program should delete the emails it finds so that it doesn’t repeat instructions every time it checks the email account. As an extra feature, have the program email or text you a confirmation every time it executes a command. Since you won’t be sitting in front of the computer that is running the program, it’s a good idea to use the logging functions (see Chapter 10) to write a text file log that you can check if errors come up.

  qBittorrent (as well as other BitTorrent applications) has a feature where it can quit automatically after the download completes. Chapter 15 explains how you can determine when a launched application has quit with the wait() method for Popen objects. The wait() method call will block until qBittorrent has stopped, and then your program can email or text you a notification that the download has completed.

  There are a lot of possible features you could add to this project. If you get stuck, you can download an example implementation of this program from http://nostarch.com/automatestuff/.

  Chapter 17. Manipulating Images

  If you have a digital camera or even if you just upload photos from your phone to Facebook, you probably cross paths with digital image files all the time. You may know how to use basic graphics software, such as Microsoft Paint or Paintbrush, or even more advanced applications such as Adobe Photoshop. But if you need to edit a massive number of images, editing them by hand can be a lengthy, boring job.

  Enter Python. Pillow is a third-party Python module for interacting with image files. The module has several functions that make it easy to crop, resize, and edit the content of an image. With the power to manipulate images the same way you would with software such as Microsoft Paint or Adobe Photoshop, Python can automatically edit hundreds or thousands of images with ease.

  Computer Image Fundamentals

  In order to manipulate an image, you need to understand the basics of how computers deal with colors and coordinates in images and how you can work with colors and coordinates in Pillow. But before you continue, install the pillow module. See Appendix A for help installing third-party modules.

  Colors and RGBA Values


  Computer programs often represent a color in an image as an RGBA value. An RGBA value is a group of numbers that specify the amount of red, green, blue, and alpha (or transparency) in a color. Each of these component values is an integer from 0 (none at all) to 255 (the maximum). These RGBA values are assigned to individual pixels; a pixel is the smallest dot of a single color the computer screen can show (as you can imagine, there are millions of pixels on a screen). A pixel’s RGB setting tells it precisely what shade of color it should display. Images also have an alpha value to create RGBA values. If an image is displayed on the screen over a background image or desktop wallpaper, the alpha value determines how much of the background you can “see through” the image’s pixel.

  In Pillow, RGBA values are represented by a tuple of four integer values. For example, the color red is represented by (255, 0, 0, 255). This color has the maximum amount of red, no green or blue, and the maximum alpha value, meaning it is fully opaque. Green is represented by (0, 255, 0, 255), and blue is (0, 0, 255, 255). White, the combination of all colors, is (255, 255, 255, 255), while black, which has no color at all, is (0, 0, 0, 255).

  If a color has an alpha value of 0, it is invisible, and it doesn’t really matter what the RGB values are. After all, invisible red looks the same as invisible black.

  Pillow uses the standard color names that HTML uses. Table 17-1 lists a selection of standard color names and their values.

  Table 17-1. Standard Color Names and Their RGBA Values

  Name

  RGBA Value

  Name

  RGBA Value

  White

  (255, 255, 255, 255)

  Red

  (255, 0, 0, 255)

  Green

  (0, 128, 0, 255)

  Blue

  (0, 0, 255, 255)

  Gray

  (128, 128, 128, 255)

  Yellow

  (255, 255, 0, 255)

  Black

  (0, 0, 0, 255)

  Purple

  (128, 0, 128, 255)

  Pillow offers the ImageColor.getcolor() function so you don’t have to memorize RGBA values for the colors you want to use. This function takes a color name string as its first argument, and the string 'RGBA' as its second argument, and it returns an RGBA tuple.

  CMYK and RGB Coloring

  In grade school you learned that mixing red, yellow, and blue paints can form other colors; for example, you can mix blue and yellow to make green paint. This is known as the subtractive color model, and it applies to dyes, inks, and pigments. This is why color printers have CMYK ink cartridges: the Cyan (blue), Magenta (red), Yellow, and blacK ink can be mixed together to form any color.

  However, the physics of light uses what’s called an additive color model. When combining light (such as the light given off by your computer screen), red, green, and blue light can be combined to form any other color. This is why RGB values represent color in computer programs.

  To see how this function works, enter the following into the interactive shell:

  ➊ >>> from PIL import ImageColor ➋ >>> ImageColor.getcolor('red', 'RGBA') (255, 0, 0, 255) ➌ >>> ImageColor.getcolor('RED', 'RGBA') (255, 0, 0, 255) >>> ImageColor.getcolor('Black', 'RGBA') (0, 0, 0, 255) >>> ImageColor.getcolor('chocolate', 'RGBA') (210, 105, 30, 255) >>> ImageColor.getcolor('CornflowerBlue', 'RGBA') (100, 149, 237, 255)

  First, you need to import the ImageColor module from PIL ➊ (not from Pillow; you’ll see why in a moment). The color name string you pass to ImageColor.getcolor() is case insensitive, so passing 'red' ➋ and passing 'RED' ➌ give you the same RGBA tuple. You can also pass more unusual color names, like 'chocolate' and 'Cornflower Blue'.

  Pillow supports a huge number of color names, from 'aliceblue' to 'whitesmoke'. You can find the full list of more than 100 standard color names in the resources at http://nostarch.com/automatestuff/.

  Coordinates and Box Tuples

  Image pixels are addressed with x- and y-coordinates, which respectively specify a pixel’s horizontal and vertical location in an image. The origin is the pixel at the top-left corner of the image and is specified with the notation (0, 0). The first zero represents the x-coordinate, which starts at zero at the origin and increases going from left to right. The second zero represents the y-coordinate, which starts at zero at the origin and increases going down the image. This bears repeating: y-coordinates increase going downward, which is the opposite of how you may remember y-coordinates being used in math class. Figure 17-1 demonstrates how this coordinate system works.

  Many of Pillow’s functions and methods take a box tuple argument. This means Pillow is expecting a tuple of four integer coordinates that represent a rectangular region in an image. The four integers are, in order, as follows:

  Figure 17-1. The x- and y-coordinates of a 27×26 image of some sort of ancient data storage device

  Left: The x-coordinate of the leftmost edge of the box.

  Top: The y-coordinate of the top edge of the box.

  Right: The x-coordinate of one pixel to the right of the rightmost edge of the box. This integer must be greater than the left integer.

  Bottom: The y-coordinate of one pixel lower than the bottom edge of the box. This integer must be greater than the top integer.

  Figure 17-2. The area represented by the box tuple (3, 1, 9, 6)

  Note that the box includes the left and top coordinates and goes up to but does not include the right and bottom coordinates. For example, the box tuple (3, 1, 9, 6) represents all the pixels in the black box in Figure 17-2.

  Manipulating Images with Pillow

  Now that you know how colors and coordinates work in Pillow, let’s use Pillow to manipulate an image. Figure 17-3 is the image that will be used for all the interactive shell examples in this chapter. You can download it from http://nostarch.com/automatestuff/.

  Once you have the image file Zophie.png in your current working directory, you’ll be ready to load the image of Zophie into Python, like so:

  >>> from PIL import Image >>> catIm = Image.open('zophie.png')

  Figure 17-3. My cat Zophie. The camera adds 10 pounds (which is a lot for a cat).

  To load the image, you import the Image module from Pillow and call Image.open(), passing it the image’s filename. You can then store the loaded image in a variable like CatIm. The module name of Pillow is PIL to make it backward compatible with an older module called Python Imaging Library, which is why you must run from PIL import Image instead of from Pillow import Image. Because of the way Pillow’s creators set up the pillow module, you must use the from PIL import Image form of import statement, rather than simply import PIL.

  If the image file isn’t in the current working directory, change the working directory to the folder that contains the image file by calling the os.chdir() function.

  >>> import os >>> os.chdir('C:\folder_with_image_file')

  The Image.open() function returns a value of the Image object data type, which is how Pillow represents an image as a Python value. You can load an Image object from an image file (of any format) by passing the Image.open() function a string of the filename. Any changes you make to the Image object can be saved to an image file (also of any format) with the save() method. All the rotations, resizing, cropping, drawing, and other image manipulations will be done through method calls on this Image object.

  To shorten the examples in this chapter, I’ll assume you’ve imported Pillow’s Image module and that you have the Zophie image stored in a variable named catIm. Be sure that the zophie.png file is in the current working directory so that the Image.open() function can find it. Otherwise, you will also have to specify the full absolute path in the string argument to Image.open().

  Working with the Image Data Type

  An Image object has several useful attributes that give you basic information about the image file it was loaded from: its width and height, the filename, and the graphics format (such as JPEG, GIF, or PNG).

  For example, ente
r the following into the interactive shell:

  >>> from PIL import Image >>> catIm = Image.open('zophie.png') >>> catIm.size ➊ (816, 1088) ➋ >>> width, height = catIm.size ➌ >>> width 816 ➍ >>> height 1088 >>> catIm.filename 'zophie.png' >>> catIm.format 'PNG' >>> catIm.format_description 'Portable network graphics' ➎ >>> catIm.save('zophie.jpg')

  After making an Image object from Zophie.png and storing the Image object in catIm, we can see that the object’s size attribute contains a tuple of the image’s width and height in pixels ➊. We can assign the values in the tuple to width and height variables ➋ in order to access with width ➌ and height ➍ individually. The filename attribute describes the original file’s name. The format and format_description attributes are strings that describe the image format of the original file (with format_description being a bit more verbose).

  Finally, calling the save() method and passing it 'zophie.jpg' saves a new image with the filename zophie.jpg to your hard drive ➎. Pillow sees that the file extension is .jpg and automatically saves the image using the JPEG image format. Now you should have two images, zophie.png and zophie.jpg, on your hard drive. While these files are based on the same image, they are not identical because of their different formats.

 

‹ Prev