摘自python3-cookbook的一些知识点
程序员文章站
2022-05-28 13:26:16
...
1.如果你想在程序的某些位置终止程序的执行(不是函数或者循环),该怎么做?
import sys
sys.stderr.write('It failed!\n')
raise SystemExit(1)
2.你希望你的脚本接受任何用户认为最简单的输入方式。包括将命令行的输出通过管道传递给该脚本、 重定向文件到该脚本,或在命令行中传递一个文件名或文件名列表给该脚本。
Python内置的 fileinput 模块让这个变得简单。如果你有一个下面这样的脚本:
#!/usr/bin/env python3
import fileinput
with fileinput.input() as f_input:
for line in f_input:
print(line, end='')
那么你就能以前面提到的所有方式来为此脚本提供输入。假设你将此脚本保存为 filein.py 并将其变为可执行文件, 那么你可以像下面这样调用它,得到期望的输出:
$ ls | ./filein.py # Prints a directory listing to stdout.
$ ./filein.py /etc/passwd # Reads /etc/passwd to stdout.
$ ./filein.py < /etc/passwd # Reads /etc/passwd to stdout.
3.你的程序如何能够解析命令行选项(位于sys.argv中)
http://python3-cookbook.readthedocs.io/zh_CN/latest/c13/p03_parsing_command_line_options.html
argparse 模块可被用来解析命令行选项。
import argparse
parser = argparse.ArgumentParser(description='Search some files')
parser.add_argument(dest='filenames',metavar='filename', nargs='*')
parser.add_argument('-p', '--pat',metavar='pattern', required=True,
dest='patterns', action='append',
help='text pattern to search for')
parser.add_argument('-v', dest='verbose', action='store_true',
help='verbose mode')
parser.add_argument('-o', dest='outfile', action='store',
help='output file')
parser.add_argument('--speed', dest='speed', action='store',
choices={'slow','fast'}, default='slow',
help='search speed')
args = parser.parse_args()
# Output the collected arguments
print(args.filenames)
print(args.patterns)
print(args.verbose)
print(args.outfile)
print(args.speed)
4.你写了个脚本,运行时需要一个密码。此脚本是交互式的,因此不能将密码在脚本中硬编码, 而是需要弹出一个密码输入提示,让用户自己输入。
import getpass
user = getpass.getuser()
passwd = getpass.getpass()
if svc_login(user, passwd): # You must write svc_login()
print('Yay!')
else:
print('Boo!')
5.你想执行一个外部命令并以Python字符串的形式获取执行结果。
try:
out_bytes = subprocess.check_output(['cmd','arg1','arg2'])
except subprocess.CalledProcessError as e:
out_bytes = e.output # Output generated before error
code = e.returncode # Return code
这段代码执行一个指定的命令并将执行结果以一个字节字符串的形式返回。 如果你需要文本形式返回,加一个解码步骤即可。例如:
out_text = out_bytes.decode(‘utf-8’)
6.你想要复制或移动文件和目录,但是又不想调用shell命令。
shutil 模块有很多便捷的函数可以复制文件和目录。使用起来非常简单,比如:
import shutil
# Copy src to dst. (cp src dst)
shutil.copy(src, dst)
# Copy files, but preserve metadata (cp -p src dst)
shutil.copy2(src, dst)
# Copy directory tree (cp -R src dst)
shutil.copytree(src, dst)
# Move src to dst (mv src dst)
shutil.move(src, dst)
7.你需要创建或解压常见格式的归档文件(比如.tar, .tgz或.zip)
shutil 模块拥有两个函数—— make_archive() 和 unpack_archive() 可派上用场。 例如:
>>> import shutil
>>> shutil.unpack_archive('Python-3.3.0.tgz')
>>> shutil.make_archive('py33','zip','Python-3.3.0')
'/Users/beazley/Downloads/py33.zip'
>>>
8.你需要写一个涉及到文件查找操作的脚本,比如对日志归档文件的重命名工具, 你不想在Python脚本中调用shell,或者你要实现一些shell不能做的功能。
查找文件,可使用 os.walk() 函数,传一个*目录名给它。 下面是一个例子,查找特定的文件名并答应所有符合条件的文件全路径:
#!/usr/bin/env python3.3
import os
def findfile(start, name):
for relpath, dirs, files in os.walk(start):
if name in files:
full_path = os.path.join(start, relpath, name)
print(os.path.normpath(os.path.abspath(full_path)))
if __name__ == '__main__':
findfile(sys.argv[1], sys.argv[2])
9.打印某个目录下所有最近被修改过的文件
import os
import time
def modified_within(top, seconds):
now = time.time()
for path, dirs, files in os.walk(top):
for name in files:
fullpath = os.path.join(path, name)
if os.path.exists(fullpath):
mtime = os.path.getmtime(fullpath)
if mtime > (now - seconds):
print(fullpath)
if __name__ == '__main__':
import sys
if len(sys.argv) != 3:
print('Usage: {} dir seconds'.format(sys.argv[0]))
raise SystemExit(1)
modified_within(sys.argv[1], float(sys.argv[2]))
10.你想通过脚本启动浏览器并打开指定的URL网页
webbrowser 模块能被用来启动一个浏览器,并且与平台无关。例如:
>>> import webbrowser
>>> webbrowser.open('http://www.python.org')
True
>>>
11.怎样捕获代码中的所有异常?
想要捕获所有的异常,可以直接捕获 Exception 即可:
try:
...
except Exception as e:
...
log('Reason:', e) # Important!
这个将会捕获除了 SystemExit 、 KeyboardInterrupt 和 GeneratorExit 之外的所有异常。 如果你还想捕获这三个异常,将 Exception 改成 BaseException 即可。
12.你在一个 except 块中捕获了一个异常,现在想重新抛出它。
简单的使用一个单独的 rasie 语句即可,例如:
>>> def example():
... try:
... int('N/A')
... except ValueError:
... print("Didn't work")
... raise
...
>>> example()
Didn't work
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in example
ValueError: invalid literal for int() with base 10: 'N/A'
>>>
13.你想测试你的程序运行所花费的时间并做性能测试。
如果你只是简单的想测试下你的程序整体花费的时间, 通常使用Unix时间函数就行了,比如:
bash % time python3 someprogram.py
real 0m13.937s
user 0m12.162s
sys 0m0.098s
bash %
如果你还需要一个程序各个细节的详细报告,可以使用 cProfile 模块:
bash % python3 -m cProfile someprogram.py
对于函数的性能测试,可以使用一个简单的装饰器:
import time
from functools import wraps
def timethis(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter()
r = func(*args, **kwargs)
end = time.perf_counter()
print('{}.{} : {}'.format(func.__module__, func.__name__, end - start))
return r
return wrapper
14.你的程序运行太慢,你想在不使用复杂技术比如C扩展或JIT编译器的情况下加快程序运行速度。
首先你得利用13中的技巧去了解程序中那些地地方存在性能问题,然后做一下几方面:
1.局部变量和全局变量各归其位,无结构的代码块要统一写到一个函数里
2.尽可能去掉属性访问
如将
import math
x = math.sqrt()
改为:
from math import sqrt
x = sqrt()
3.理解局部变量
#对于频繁访问的名称,通过将这些名称变成局部变量可以加速程序运行
import math
def compute_roots(nums):
sqrt = math.sqrt
4.避免不必要的抽象
5.使用内置的容器
6.避免创建不必要的数据结构或复制
7.对于算法的选型也很重要