python实践项目(五)

来源:互联网 发布:ubuntu 安装lnmp php7 编辑:程序博客网 时间:2024/06/05 15:34

参考书目:《Python编程快速上手—让繁琐工作自动化》,下载地址:我是下载链接,请点击

练习1:口令保管箱

       你可能在许多不同网站上拥有账号,每个账号使用相同的口令是个坏习惯。如果这些网站中任何一个有安全漏洞,黑客就会知道你所有的其他账号的口令。最好是在你的计算机上,使用口令管理器软件,利用一个主控口令,解锁口令管理器。然后将某个账户口令拷贝到剪贴板,再将它粘贴到网站的口令输入框。

 你在这个例子中创建的口令管理器程序并不安全,但它基本展示了这种程序的工作原理 。
第 1 步: 程序设计和数据结构
  你希望用一个命令行参数来运行这个程序,该参数是账号的名称。例如, 账号的口令将拷贝到剪贴板,这样用户就能将它粘贴到口令输入框。通过这种方式,用户可以有很长而复杂的口令,又不需要记住它们。打开一个新的文件编辑器窗口,将该程序保存为pw.py。程序开始时需要有一行#!(参见附录B), 并且应该写一些注释, 简单描述该程序。因为你希望关联每个账号的名称及其口令, 所以可以将这些作为字符串保存在字典中。字典将是组织你
的账号和口令数据的数据结构。让你的程序看起来像下面这样:
 

#! python3# pw.py - An insecure password locker program.PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6','blog': 'VmALvQyKAxiVH5G8v01if1MLZF3sdt','luggage': '12345'}

第 2 步: 处理命令行参数
命令行参数将存储在变量sys.argv中(关于如何在程序中使用命令行参数,更多信息请参见附录B)。sys.argv列表中的第一项总是一个字符串,它包含程序的文件名('pw.py')。第二项应该是第一个命令行参数。对于这个程序,这个参数就是账户名称,你希望获取它的口令。因为命令行参数是必须的,所以如果用户忘记添加参数(也就是说,如果列表中少于两个值),你就显示用法信息。让你的程序看起来像下面这样: 

#! python3# pw.py - An insecure password locker program.PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6','blog': 'VmALvQyKAxiVH5G8v01if1MLZF3sdt','luggage': '12345'}import sysif len(sys.argv) < 2:print('Usage: python pw.py [account] - copy account password')sys.exit()account = sys.argv[1] # first command line arg is the account name

第 3 步: 复制正确的口令
既然账户名称已经作为字符串保存在变量account中, 你就需要看看它是不是PASSWORDS字典中的键。如果是, 你希望利用pyperclip.copy(), 将该键的值复制到剪贴板(既然用到了pyperclip模块,就需要导入它)。请注意,实际上不需要account变量,你可以在程序中所有使用account的地方,直接使用sys.argv[1]。但名为account
的变量更可读, 不像是神秘的 sys.argv[1]
让你的程序看起来像这样:

#! python3# pw.py - An insecure password locker program.PASSWORDS = {'email': 'F7minlBDDuvMJuxESSKHFhTxFtjVB6','blog': 'VmALvQyKAxiVH5G8v01if1MLZF3sdt','luggage': '12345'}import sys, pyperclipif len(sys.argv) < 2:print('Usage: py pw.py [account] - copy account password')sys.exit()account = sys.argv[1] # first command line arg is the account nameif account in PASSWORDS:pyperclip.copy(PASSWORDS[account])print('Password for ' + account + ' copied to clipboard.')else:print('There is no account named ' + account)

       这段新代码在 PASSWORDS字典中查找账户名称。如果该账号名称是字典中的键, 我们就取得该键对应的值, 将它复制到剪贴板, 然后打印一条消息, 说我们已经复制了该值。否则, 我们打印一条消息, 说没有这个名称的账号。这就是完整的脚本。利用附录B中的指导, 轻松地启动命令行程序, 现在你就有了一种快速的方式, 将账号的口令复制到剪贴板。如果需要更新口令, 就必须修改源代码的PASSWORDS字典中的值。当然,你可能不希望把所有的口令都放在一个地方,让某人能够轻易地复制。但你可以修改这个程序,利用它快速地将普通文本复制到剪贴板。假设你需要发出一些电子邮件,它们有许多同样的段落。你可以将每个段落作为一个值, 放在PASSWORDS字典中(此时你可能希望对这个字典重命名), 然后你就有了一种方式, 快速地选择一些标准的文本, 并复制到剪贴板。

Windows上, 你可以创建一个批处理文件,利用Win-R运行窗口, 来运行这个程序(关于批处理文件的更多信息,参见附录B)。在文件编辑器中输入以下代码, 保存为pw.bat, 放在C:\Windows目录下:      

@py.exe C:\Python34\pw.py %*@pause

       有了这个批处理文件,在 Windows上运行口令保存程序,就只要按下Win-R,再输入pw <account name> 例如:pw email


练习2:在Wiki标记中添加无序列表

在编辑一篇维基百科的文章时,你可以创建一个无序列表,即让每个列表项占据一行,并在前面放置一个星号。但是假设你有一个非常大的列表,希望添加前面的星号。你可以在每一行开始处输入这些星号,一行接一行。或者也可以用一小段Python脚本, 将这个任务自动化。bulletPointAdder.py脚本将从剪贴板中取得文本, 在每一行开始处加上星号和空格, 然后将这段新的文本贴回到剪贴板。例如, 如果我将下面的文本复制到剪贴板(取自于维基百科的文章“List of Lists of Lists”): 

Lists of animalsLists of aquarium lifeLists of biologists by author abbreviationLists of cultivars

然后运行bulletPointAdder.py 程序, 剪贴板中就会包含下面的内容:

* Lists of animals* Lists of aquarium life* Lists of biologists by author abbreviation* Lists of cultivars

      这段前面加了星号的文本, 就可以粘贴回维基百科的文章中, 成为一个无序列表。
      第 1 步: 从剪贴板中复制和粘贴
你希望 bulletPointAdder.py程序完成下列事情:
1. 从剪贴板粘贴文本;
2.对它做一些处理;
3.将新的文本复制到剪贴板。
2 步有一点技巧,但第1 步和第 3步相当简单,它们只是利用了 pyperclip.copy()pyperclip.paste()函数。现在,我们先写出程序中第1 步和第 3步的部分。输入以下代码,将程序保存为 bulletPointAdder.py 

#! python3# bulletPointAdder.py - Adds Wikipedia bullet points to the start# of each line of text on the clipboard.import pypercliptext = pyperclip.paste()# TODO: Separate lines and add stars.pyperclip.copy(text)

        TODO 注释是提醒, 你最后应该完成这部分程序。下一步实际上就是实现程序
的这个部分。
 

第 2 步: 分离文本中的行, 并添加星号
调用 pyperclip.paste()将返回剪贴板上的所有文本,结果是一个大字符串。如果我们使用“List of Lists of Lists”的例子, 保存在 text 中的字符串就像这样: 

'Lists of animals\nLists of aquarium life\nLists of biologists by authorabbreviation\nLists of cultivars'

在打印到剪贴板,或从剪贴板粘贴时,该字符串中的\n换行字符, 让它能显示为多行。在这一个字符串中有许多“行”。 你想要在每一行开始处添加一个星号。你可以编写代码,查找字符串中每个\n换行字符, 然后在它后面添加一个星号。但更容易的做法是, 使用 split()方法得到一个字符串的列表,其中每个表项就是原来字符串中的一行, 然后在列表中每个字符串前面添加星号。
让程序看起来像这样:

#! python3# bulletPointAdder.py - Adds Wikipedia bullet points to the start# of each line of text on the clipboard.import pypercliptext = pyperclip.paste()# Separate lines and add stars.lines = text.split('\n')for i in range(len(lines)): # loop through all indexes in the "lines" listlines[i] = '* ' + lines[i] # add star to each string in "lines" listpyperclip.copy(text)
我们按换行符分割文本,得到一个列表,其中每个表项是文本中的一行。我们将列表保存在 lines中,然后遍历 lines中的每个表项。对于每一行, 我们在开始处添加一个新号和一个空格。现在lines 中的每个字符串都以星号开始。

第 3 步: 连接修改过的行
lines 列表现在包含修改过的行, 每行都以星号开始。但 pyperclip.copy()需要一个字符串, 而不是字符串的列表。要得到这个字符串,就要将lines 传递给 join 法,连接列表中字符串。让你的程序看起来像这样: 

#! python3# bulletPointAdder.py - Adds Wikipedia bullet points to the start# of each line of text on the clipboard.import pypercliptext = pyperclip.paste()# Separate lines and add stars.lines = text.split('\n')for i in range(len(lines)): # loop through all indexes for "lines" listlines[i] = '* ' + lines[i] # add star to each string in "lines" listtext = '\n'.join(lines)pyperclip.copy(text)
运行这个程序,它将取代剪贴板上的文本,新的文本每一行都以星号开始。现在程序完成了,可以在剪贴板中复制一些文本,试着运行它。即使不需要自动化这样一个专门的任务,也可能想要自动化某些其他类型的文本操作,诸如删除每行末尾的空格,或将文本转换成大写或小写。不论你的需求是什么,都可以使用剪贴板作为输入和输出。

练习3:表格打印      

  编写一个名为printTable()的函数, 它接受字符串的列表的列表,将它显示在组:织良好的表格中, 每列右对齐。假定所有内层列表都包含同样数目的字符串。例如,该值可能看起来像这样:

tableData = [['apples', 'oranges', 'cherries', 'banana'],['Alice', 'Bob', 'Carol', 'David'],        ['dogs', 'cats', 'moose', 'goose']]
你的printTable()函数将打印出:
apples Alice dogsoranges Bob catscherries Carol moosebanana David goose

提示:你的代码首先必须找到每个内层列表中最长的字符串,这样整列就有足够的宽度以放下所有字符串。你可以将每一列的最大宽度,保存为一个整数的列表。printTable()函数的开始可以是colWidths = [0] * len(tableData),这创建了一个列表,它包含了一些0,数目与tableData中内层列表的数目相同。这样,colWidths[0]就可以保tableData[0]中最长字符串的宽度,colWidths[1]就可以保存tableData[1]中最长字符串的宽度,以此类推。然后可以找到colWidths列表中最大的值,决定将什么整数宽度传递给rjust()字符串方法。

       参考代码如下:     

#-*-coding:utf-8-*-tableData = [['apples', 'oranges', 'cherries', 'banana'],            ['Alice', 'Bob', 'Carol', 'David'],            ['dogs', 'cats', 'moose', 'goose']]def findMaxLen(listData):    maxLen = 0    for i in range(len(listData)):        if maxLen < len(listData[i]):            maxLen = len(listData[i])    return maxLensubListLen = len(tableData)     # 列表tableData中子列表的个数colWidths = [0]*subListLen      # 保存每一个列表的最大宽度,*操作符可以用于一个列表和一个整数,实现列表的复制ListNum = len(tableData[0])     # 每个子列表的元素个数(假设相等)for i in range(subListLen):    colWidths[i] = findMaxLen(tableData[i])for i in range(ListNum):    for j in range(subListLen):        # print(tableData[j][i].rjust(colWidths[j]+2),end= '')        print(tableData[j][i].ljust(colWidths[j] + 2), end='')    print()

原创粉丝点击