一、什么是函数
函数基本概念
1、函数是对程序逻辑进行结构化或过程化的一种编程方法
2、将整块代码巧妙地隔离成易于管理的小块
3、把重复代码放到函数中而不是进行大量的拷贝,这样既能节省空间,也有助于保持一致性
4、通常函数都是用于实现某一种功能
函数格式
python定义函数使用def关键字,一般格式如下
def 函数名(参数列表): 函数体
函数名的命名规则:
函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号;
函数名是区分大小写的。
函数名不能是保留字
函数 vs 过程
1、两者都是可以被调用的实体
2、传统意义上的的函数,可能不带任何输入参数,经过一定的处理,最后向调用者传回返回值
3、其中一些函数则是布尔类型,返回一个零值或非零值
4、过程是简单、特殊、没有返回值的函数
5、Python的过程就是函数,因为解释器会隐式地返回默认值None
返回值与函数类型
1、函数会向调用者返回一个值,而实际编程中大部分偏函数更接近过程,不显示地返回任何东西
2、把过程看待成函数的语言通常对于"什么都不返回"的函数设定了特殊的类型或者值的名字 ,这些函数在Python中对应的返回对象类型是none
3、当没有显式地返回元素或如果返回None时,Python会返回一个None
下面的hello()函数就像一个过程,没有返回值。如果保存了返回值,则该值为None
>>> def hello(): print "hello world" >>> hello() hello world >>> res = hello() hello world >>> res >>> print res None >>> type(res) <type 'NoneType'> >>>
| 返回的对象的数目 | Python实际返回的对象 |
|---|---|
| 0 | None |
| 1 | object |
| >1 | tuple |
上表总结了从一个函数中返回的对象的数目,以及Python实际返回的对象
4种函数的类型
函数根据有没有参数,有没有返回值,可以相互组合,一共有4种
1、无参数,无返回值 2、无参数,有返回值 3、有参数,无返回值 4、有参数,有返回值
注意:
写函数,不要在函数中写print() 函数是以功能为导向的,除非测试的时候,才可以写print()
无参数,无返回值的函数
1、此类函数,不能接收参数,也没有返回值,一般情况下,打印提示灯类似的功能,使用这类的函数
def printMenu():
print('--------------------------')
print(' xx涮涮锅 点菜系统')
print('')
print(' 1. 羊肉涮涮锅')
print(' 2. 牛肉涮涮锅')
print(' 3. 猪肉涮涮锅')
print('--------------------------')
printMenu()
执行结果:
-------------------------- xx涮涮锅 点菜系统 1. 羊肉涮涮锅 2. 牛肉涮涮锅 3. 猪肉涮涮锅 --------------------------
无参数,有返回值的函数
1、此类函数,不能接收参数,但是可以返回某个数据,一般情况下,像采集数据,用此类函数
#!/usr/bin/env python
#coding:utf8
def getTemperature():
# 这里是获取温度的一些处理过程
# 为了简单起见,先模拟返回一个数据
return 24
temperature = getTemperature()
print('当前的温度为:%d' % temperature)
执行结果:
当前的温度为:24
2、一个函数到底有没有返回值,就看有没有return,因为只有return才可以返回数据
3、函数中,可以有多个return语句,但是只要执行到一个return语句,那么就意味着这个函数的调用完成
有参数,无返回值的函数
def 函数名(形参列表): 语句
此类函数,能接收参数,但不可以返回数据,一般情况下,对某些变量设置数据而不需结果时,用此类函数
在调用函数时,如果需要把一些数据一起传递过去,被调用函数就需要用参数来接收
参数列表中变量的个数根据实际传递的数据的多少来确定
有参数,有返回值的函数
此类函数,不仅能接收参数,还可以返回某个数据,一般情况下,像数据处理并需要结果的应用,用此类函数
# 计算1~num的累积和
def calculateNum(num):
result = 0
i = 1
while i<=num:
result = result + i
i+=1
return result
result = calculateNum(100)
print('1~100的累积和为:%d'%result)
执行结果:
1~100的累积和为:5050
分析:
1.定义函数calculateNum(num),把参数100加入到传递到num中
2.把0赋值给result,1赋值给i然后进行判断;假若i的值小于等于参数100则执行while循环,否则执行return result
3.执行完函数里面的语句后执行result = calculateNum(100),即把返回值赋值给result,最终打印result
二、调用函数
1、调用的方式为函数名([实参列表])
2、如果调用的函数 在定义时有形参,那么在调用的时候就应该传递参数
3、调用时,实参的个数和先后顺序应该和定义函数中要求的一致
4、如果调用的函数有返回值,那么就可以用一个变量来进行保存这个值
函数操作符
1、同大多数语言相同,python用一对圆括号调用函数
2、如果没有加圆括号,只是对函数的引用
3、任何输入的参数都必须放置在括号中
4、作为函数声明的一部分,括号也会用来定义那些参数
#!/usr/bin/env python #coding:utf8 def foo(): print 'hello' foo() print foo
执行结果:
hello <function foo at 0x000000000351FDD8>
函数的执行顺序
例子1:
def fun(): print 'test1' def fun(): print 'test2' fun()
执行结果:
test2
下面的fun将上面的fun覆盖掉了;因此若是定义函数名时,若有同名的函数,则靠近调用语句的函数生效
例子2:
#!/usr/bin/env python #coding:utf-8 def x(fun): def y(): print 'test1' return y def f(): print 'test2' x(f)
x(f),注意:x(f)中的f没有加括号(),即f为参数。将f作为参数传入x(),x()中的y()函数返回的是y即函数名所以没有执行y函数。所以最终打印出为无结果。
例子3:
#!/usr/bin/env python #coding:utf-8 def x(fun): def y(): print 'test1' return y def f(): print 'test2' x(f())
执行结果:
test2
x(f()),注意:x(f())中f后面是有括号的,即f作为函数传给x。将f()函数传给x()函数,先执行f()函数打印出test2,再执行x()函数,因为x()中的y()函数返回的是y即函数名所以没有执行y函数。所以最终打印结果为test2。
例子4:
#!/usr/bin/env python #coding:utf-8 def x(fun): def y(): print 'test1' return y() def f(): print 'test2' x(f)
执行结果
test1
x(f),注意:x函数中的y函数返回的值是y函数,即return y()。x(f)中f作为参数传给x函数,所以f()函数就不执行了,执行x函数,因为return y(),所以执行y函数打印出test1。最终打印结果为test1。
例子5:
def x(fun): def y(): print 'test1' return y() def f(): print 'test2' x(f())
执行结果:
test2 test1
x(f()),注意:x(f())中f后面是有括号的,即f作为函数传给x;x函数中的y函数返回的值是y函数,即return y()。将f()函数传给x()函数,先执行f()函数打印出test2,再执行x函数,因为return y(),所以执行y函数打印出test1。最终执行打印结果为test2 test1。
例子6:
#!/usr/bin/env python #coding:utf-8 def x(fun): def y(): print 'test1' print fun() return y() def f(): return 'test2' x(f)
执行结果:
test1 test2
x(f),注意:x(f)中f后面没有括号,即f作为参数传入x()函数。将f作为参数带入x函数执行,因为return y()所以执行y函数打印出ttest1;再执行print fun()语句,此时相当于func()=f(),即开始执行f()函数打印出test2。所以最终打印结果为test1 test2
三、创建函数
def语句
1、函数是用def语句来创建的,语法如下:
def function_name(arguments): "function_documentation_string" function_body_suite
2、标题行由def关键字,函数的名字,以及参数的集合(如果有的话)组成
3、def子句的剩余部分包括了一个虽然可选但是强烈推荐的文档字串,和必需的函数体
3、函数外部的代码要想获取函数的执行结果,就可以在函数里面用return语句,把结果返回
4、通常函数体内有多条return语句;一旦第一个return语句得到执行,整个函数将立即终止;
5、如果return 后面带一个print 或者return ,则后面的不执行
6、如果未在函数中指定return,那么这个函数的返回值就是None
7、return 语句是Python语言中函数返回的一个值,每个函数都应该有一个返回值;其中,return返回值可以是一个数值,一个字符串,一个布尔值或者一个列表。
8、return语句可以出现在函数体中的任何位置
9、在函数定义中,形式参数和return语句都是可选的
10、return表示函数调用的结束,并将结果返回至函数调用处
函数中一定要有return 返回值才是完整的函数,如果你没有定义Python 函数返回值,那么得到一个结果是None对象,而None表示没有任何值
下面举个例子:
编辑
通过这两个简单的对比,大家是不是能看出来return的重要性了吧。其实return没有什么特别的用法,只需要记住函数要有返回值即可。
前向引用
1、函数不允许在函数未声明之前对其进行引用或者调用
在函数bar()没有声明之前:
def foo(): print 'in foo' bar() foo() #报错,因为bar没有定义,名字错误是当访问没有初始化的标识符时才产生的异常
定义完bar()函数之后
def foo(): print 'in foo' bar() def bar(): print 'in bar' foo() #正常执行,虽然bar的定义在foo定义后面
因为即使 在 foo()中对 bar()进行的调用出现在 bar()的定义之前,但 foo()本身不是在 bar()声明之前被调用的。换句话说,我们声明 foo(),然后再声明 bar(),接着调用 foo(),但是到那时,bar()已经存在了,所以调用成功
执行结果:
in foo in bar
函数属性
1、你可以获得每个python模块、类和函数中任意的名称空间
2、你可以在模块 foo 和 bar 里都有名为 x 的一个变量,,但是在将这两个模块导入你的程序后,仍然可以使用这两个变量。所以,
即使在两个模块中使用了相同的变量名字,这也是安全的,因为句点属性标识对于两个模块意味了不同的命名空间 3、函数属性是python另外一个使用了句点属性标识并拥有名字空间的领域
def foo(): 'foo() -- properly created doc string' def bar(): pass bar.__doc__ = 'Oops, forgot the doc str above' bar.version = 0.1
执行结果:
>>> help(foo) Help on function foo in module __main__: foo() foo() -- properly created doc string >>> print bar.version 0.1 >>> print foo.__doc__ foo() -- properly created doc string >>> print bar.__doc__ Oops, forgot the doc str above
内部/内嵌函数
1、在函数体内创建另外一个函数是完全合法的,这种函数叫做内部/内嵌函数
2、有时也叫嵌套函数
3、最明显的创造内部函数的方法是在外部函数的定义体内定义函数(用 def 关键字) 4、内部函数一个有趣的方面在于整个函数体都在外部函数的作用域之内。
5、一个函数里面又调用了另外一个函数,这就是所谓的函数嵌套调用
例子1:
#!/usr/bin/env python #coding:utf-8 def foo(): def bar(): print "bar() is called" print 'foo() is called ' bar() foo()
执行结果:
foo() is called bar() is called
例子2:
#!/usr/bin/env python #coding:utf-8 def foo(): def bar(): print "bar() is called" print 'foo() is called ' bar() print foo() #因为当没有显式地返回元素或如果返回None时,Python会返回一个None
执行结果:
foo() is called bar() is called None
例子3:
>>> def foo(): ... def bar(): ... print 'bar() is called' ... print 'foo() is called' ... bar() >>> foo() foo() is called bar() is called >>> bar() Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'bar' is not defined
如果没有任何对 bar()的外部引用,那么除了在函数体内,任何地方都不能对其进行调用,这就是在上述代码执行到最后你看到异常的原因
例子4:
#!/usr/bin/env python #coding:utf8 def testB(): print '---- testB start----' print '这里是testB函数执行的代码...(省略)...' print '---- testB end----' def testA(): print '---- testA start----' testB() print '---- testA end----' testA()
执行结果:
---- testA start---- ---- testB start---- 这里是testB函数执行的代码...(省略)... ---- testB end---- ---- testA end----
如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次 函数A执行的位置
函数的返回值
1、多数情况下,函数并不直接输出数据,而是向调用者返回值
2、函数的返回值使用return关键字
3、没有return的话,函数默认返回None
>>> def foo(): ... res = 3 + 4 >>> i = foo() >>> print i None
总结:
return的作用。 1.在函数中,遇到return结束函数。 2.将值返回给函数的调用者。
四、函数参数
定义参数
1、形式参数:函数定义时,紧跟在函数名后(圆括号内)的参数被称为形式参数,简称形参。由于它不是实际存在变量,所以又称虚拟变量;
在定义函数和函数体的时候使用形参,目的就是在函数调用的时候接收实参(实参个数,类型应与实参一一对应)
2、实际参数:在主调函数中调用一个函数时,函数名后面括弧中的参数称为“实际参数”,简称实参;
调用函数时候传给函数的变量,可以是常量,变量,表达式,函数,传给形参
3、形参是虚拟的,不占用内存空间,形参变量只有在调用时才分配内存单元,实参是一个变量,占用空间,数据传送单向,只能实参传给形参,不能形参传给实参。
传递参数
1、调用函数时,实参的个数需要与形参个数一致
2、实参将依次传递给形参
>>> def foo(x, y): ... print 'x=%d, y=%d' % (x, y) >>> foo() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: foo() takes exactly 2 arguments (0 given) >>> foo(3) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: foo() takes exactly 2 arguments (1 given) >>> foo(3, 4) x=3, y=4
位置参数
1、与shell脚本类似,程序名以及参数都以位置参数的方式传递给python程序 2、使用sys模块的argv列表接收
3、位置参数必须以在被调用函数中定义的准确顺序来传递
4、另外,没有任何默认参数(见下一个部分)的话,传入函数(调用)的参数的精确的数目必须和声明的数字一致。
[root@py01 bin]# vim args.py #!/usr/bin/env python import sys print sys.argv [root@py01 bin]# ./args.py hello world ['./args.py', 'hello', 'world']
默认参数
1、默认参数就是声明了默认值的参数 2、因为给参数赋予了默认值,所以在函数调用时,不向该参数传入值也是允许的
3、python 中用默认值声明变量的语法是所有的位置参数必须出现在任何一个默认参数之前
def func(posargs, defarg1=dval1, defarg2=dval2,...): "function_documentation_string" function_body_suite
例子:
>>> def pstar(num = 30): ... print '*' * num ... >>> pstar() ****************************** >>> pstar(40) ****************************************
关键字参数
1、关键字参数的概念仅仅针对函数的调用
2、这种理念是让调用者通过函数调用中的参数名字来区分参数
3、这种规范允许参数或者不按顺序,因为解释器能通过给出的关键字来匹配参数的值
4、当参数允许"缺失“的时候,也可以使用关键字参数.这取决于函数的默认参数
#!/usr/bin/env python
#coding:utf8
def getInfo(name, age):
print "%s's age is %s" % (name, age)
getInfo('bob',23)
getInfo(age = 23, name = 'bob')
执行结果:
bob's age is 23 bob's age is 23
参数组
1、Python 同样允许程序员执行一个没有显式定义参数的函数,
2、相应的方法是通过一个把元组(非关键字参数)或字典(关键字参数)作为参数组传递给函数 3、存在这样的特性允许你把变量放在元组和/或者字典里,并在没有显式地对参数进行逐个声明的情况下,调用函数
4、可变长的参数组必须在位置参数和默认参数之后
5、语法:
func(*tuple_grp_nonkw_args, **dict_grp_kw_args)
6、其中的 tuple_grp_nonkw_args 是以元组形式体现的非关键字参数组, dict_grp_kw_args 是装有关键字参数的字典
7、实际上,你也可以给出形参!这些参数包括标准的位置参数和关键字参数,所以在 python 中允许的函数调用的完整语法为 :
func(positional_args, keyword_args,*tuple_grp_nonkw_args, **dict_grp_kw_args)
该语法中的所有的参数都是可选的---从参数传递到函数的过程来看,在单独的函数调用时,每个参数都是独立的
例子1:# 注意传递的参数对应
#!/usr/bin/env python #coding:utf8 def fun(a, b, *args, **kwargs): """可变参数演示示例""" print "a =", a print "b =", b print "args =", args print "kwargs: " for key, value in kwargs.items(): print key, "=", value fun(1, 2, 3, 4, 5, m=6, n=7, p=8) # 注意传递的参数对应
执行结果:
a = 1 b = 2 args = (3, 4, 5) kwargs: p = 8 m = 6 n = 7
例子2:# 注意元组与字典的传参方式
#!/usr/bin/env python
#coding:utf8
def fun(a, b, *args, **kwargs):
"""可变参数演示示例"""
print "a =", a
print "b =", b
print "args =", args
print "kwargs: "
for key, value in kwargs.items():
print key, "=", value
c = (3, 4, 5)
d = {"m":6, "n":7, "p":8}
fun(1, 2, *c, **d) # 注意元组与字典的传参方式
执行结果:
a = 1 b = 2 args = (3, 4, 5) kwargs: p = 8 m = 6 n = 7
例子3:
#!/usr/bin/env python
#coding:utf8
def fun(a, b, *args, **kwargs):
"""可变参数演示示例"""
print "a =", a
print "b =", b
print "args =", args
print "kwargs: "
for key, value in kwargs.items():
print key, "=", value
c = (3, 4, 5)
d = {"m":6, "n":7, "p":8}
fun(1, 2, c, d) # 注意不加星号与上面的区别
执行结果:
a = 1
b = 2
args = ((3, 4, 5), {'p': 8, 'm': 6, 'n': 7})
kwargs:
例子4: 多个单个变量,整合成元组
def func(*args): print args # 执行方式一 func(11,33,4,4454,5) #输出结果:(11,33,4,4454,5) # 执行方式二 li = [11,2,2,3,3,4,54] func(li) #输出结果:([11,2,2,3,3,4,54]) #如果想输入的列表,不想让列表称谓元组里的仅一个元素而是让列表的元素成为元组的元素加*即可 func(*li) #输出结果:(11,2,2,3,3,4,54) ############################################################# 1、接受多个参数 2、内部自动构造元组 3、序列,*,避免内部构造元组
执行结果:
(11, 33, 4, 4454, 5) ([11, 2, 2, 3, 3, 4, 54],) (11, 2, 2, 3, 3, 4, 54)
例子5:整合为字典变量
#!/usr/bin/env python
#coding:utf8
def func(**kwargs):
print kwargs
# 执行方式一
func(name='tom',age=18)
# 执行方式二
li = {'name':'tom', 'age':18, 'gender':'male'}
func(**li)
执行结果:
{'age': 18, 'name': 'tom'}
{'gender': 'male', 'age': 18, 'name': 'tom'}
例子6:整合了*args,**args
#!/usr/bin/env python #coding:utf-8 def func(*args, **drgs): print args print drgs func(11,22,33,44,k1='tom',k2='jack')
执行结果:
(11, 22, 33, 44)
{'k2': 'jack', 'k1': 'tom'}
下面是一些函数编程的练习:
mtping.py内容:
#!/usr/bin/env python
#coding:utf8
import os
def ping(ip):
result = os.system("ping -c2 %s &>/dev/null" %ip)
if result:
print "%s:down " % ip
else:
print "%s:up" % ip
if __name__ == "__main__":
for i in range(1,255):
ipaddr = "172.40.2.%s" % i
ping(ipaddr)
import os
import threading
def ping(ip):
result = os.system("ping -c2 %s &>/dev/null" %ip)
if result:
print "%s:down " % ip
else:
print "%s:up" % ip
if __name__ == "__main__":
for i in range(1,255):
ipaddr = "172.40.2.%s" % i
t = threading.Thread(target=ping,args=[ipaddr])
ping(ipaddr)
#!/usr/bin/env python
#coding:utf8
import random
import string
all_chs = string.letters + string.digits
def gen_pass():
pwd = ''
num = int(raw_input("number: "))
for i in range(num):
ch = random.choice(all_chs)
pwd += ch
print pwd
if __name__ == "__main__":
gen_pass()
#!/usr/bin/env python #coding:utf8 import random import string all_chs = string.letters + string.digits def gen_pass(num=8): pwd = '' for i in range(num): ch = random.choice(all_chs) pwd += ch return pwd if __name__ == "__main__": print gen_pass(5) print gen_pass() print gen_pass(10)
#!/usr/bin/env python
#coding:utf8
import os
def get_fname():
while True:
fname = raw_input("filename: ")
if not os.path.exists(fname):
break
print "%s already exists.Try again" % fname
return fname
def get_contents():
contents = []
while True:
data = raw_input("(Enter to quit)>")
if not data:
break
contents.append(data + '\n')
return contents
def wfile(fname,contents):
fobj = open(fname,'w')
fobj.writelines(contents)
fobj.close()
if __name__ == "__main__":
filename = get_fname()
lines = get_contents()
wfile(filename,lines)
#!/bin/bash
if [ -z "$3" ];then
echo "Usage: $0 ipfile oldpass newpass"
exit 1
fi
ipfile=$1
oldpass=$2
newpass=$3
if [! -f $ipfile ];then
echo "$ipfile does not exists"
exit 2
fi
for ip in $(cat $ipfile)
do
expect <<EOF
spawn ssh root@$ip "echo $newpass | passwd --stdin root"
expect "(yes/no)?"{
send "yes\r"
expect "password:"
send "$oldpass\r"
} "password:" { send "$oldpass\r"}
expect eof
EOF
done
执行结果:
chmod +x chpwd.sh ./chpwd.sh ./chpwd.sh ipaddr.txt redhat redhat
而在Python中,可以通过paramiko模块实现
chpwd.py内容:远程改密码
方法1:
#!/usr/bin/env python import sys import paramiko def remote_comm(host,pwd,comm): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host,username='root',password=pwd) stdin,stdout,stderr = ssh.exec_command(comm) print stdout.read(), print stderr.read(), if __name__ == "__main__": if len(sys.argv) !=4: print "Usage: %s ipfile oldpass newpass" % sys.argv[0] else: ipfile = sys.argv[1] oldpass = sys.argv[2] newpass = sys.argv[3] ch_pwd = "echo %s | passwd --stdin root" % newpass fobj = open(ipfile) for line in fobj: ip = line.strip() remote_comm(ip,oldpass,ch_pwd)
[root@host-192-168-3-6 test]# chmod +x chpwd.py [root@host-192-168-3-6 test]# cat ipaddr.txt 192.168.3.6 root@host-192-168-3-6 test]# ./chpwd.py ipaddr.txt abc123 abc123 Changing password for user root. passwd: all authentication tokens updated successfully.
#!/usr/bin/env python
import sys
import paramiko
import threading
def remote_comm(host,pwd,comm):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host,username='root',password=pwd)
stdin,stdout,stderr = ssh.exec_command(comm)
print stdout.read(),
print stderr.read(),
if __name__ == "__main__":
if len(sys.argv) !=4:
print "Usage: %s ipfile oldpass newpass" % sys.argv[0]
else:
ipfile = sys.argv[1]
oldpass = sys.argv[2]
newpass = sys.argv[3]
ch_pwd = "echo %s | passwd --stdin root" % newpass
fobj = open(ipfile)
for line in fobj:
ip = line.strip()
t = threading.Thread(target=remote_comm,args=(ip,oldpass,ch_pwd))
t.start()
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import string
alphas = string.letters + '_'
nums = string.digits
print 'Welcome to my id check prog'
inp = raw_input('Enter a id: ')
if inp[0] not in alphas: #判断首字符是否合法
print 'bad identifier'
else:
for otherchar in inp[1:]: #判断其余字符是否合法
if otherchar not in (alphas + nums):
print 'bad other char'
break
else: #注意此处的 else 是 for 结构的一部分
print '%s is good' % inp
执行结果:
Welcome to my id check prog Enter a id: 123 bad identifier
方法2:
#!/usr/bin/env python
#coding:utf8
import string
first_chs = string.letters + '_'
other_chs = first_chs + string.digits
def check_id(myid):
if myid[0] not in first_chs:
print "1st char invalid."
return
for ind,ch in enumerate(myid[1:]):
if ch not in other_chs:
print "char in position:%s invalid" % (ind +2)
break
else:
print "%s is valid" % myid
if __name__ == "__main__":
myid = raw_input("id to check: ")
if myid:
check_id(myid)
else:
print "You must input an identifier."
执行结果:
id to check: 124 1st char invalid.
编写 formatoutput.py 脚本,主要要求如下:
1、提示用户输入(多行)数据 2、假定屏幕的宽度为 50,用户输入的多行数据如下显示(文本内容居中) :
方案 为了实现文本内容居中,可以在字符串的两端打印相关的“+”号和空格即可。 字符串每一侧打印的空格数可以使用屏幕宽度减去字符串长度再除以 2 得到。 这里要注 意的是如果字符串的长度为奇数,那么将会少打印一个空格。可以在做除法时,把余数保留 下来,字符串左侧打印的空格数为除法的商值,右侧打印的空格数为商值加余数
方法1:
#!/usr/bin/env python
#coding:utf8
width = 48
data = [] #定义列表用于存储用户数据
while True:
entry = raw_input('enter data(. to quit)> ')
if entry == '.':
break
data.append(entry)
print '+' + '*' * width + '+'
for item in data:
length, extra = divmod((width - len(item)) , 2)
print '+' + ' ' * length + item + ' ' * (length + extra) + '+'
print '+' + '*' * width + '+'
enter data(. to quit)> hello enter data(. to quit)> great work enter data(. to quit)> . +************************************************+ + hello + + great work + +************************************************+
#!/usr/bin/env python
#coding:utf8
def get_contents():
contents = []
while True:
data = raw_input("(Enter to quit)>")
if not data:
break
contents.append(data)
return contents
if __name__ == '__main__':
width = 48
lines = get_contents()
print "+%s+" %('*' * width)
for line in lines:
sp_wid,extra = divmod((width-len(line)),2)
print "+%s%s%s+" % (' ' * sp_wid,line,' ' * (sp_wid+extra))
print "+%s+" % ('*' * width)
(Enter to quit)>hello (Enter to quit)>great work (Enter to quit)> +************************************************+ + hello + + great work + +************************************************+
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import string
import random
import os
allChs = string.letters + string.digits
#以下三行为字符串模板的字符串
patt = """your account is created.
username: $user
password: $pwd"""
def genPwd(num = 8): #生成随机密码函数
pwd = ''
for i in range(num):
pwd += random.choice(allChs)
return pwd
if __name__ == '__main__':
username = raw_input('username: ')
password = genPwd()
os.system('useradd %s' % username)
os.system('echo %s | passwd --stdin %s' % (password, username))
t = string.Template(patt)
os.system("echo '%s' | mail -s 'create user' root" % t.substitute(user = username,pwd = password))
[root@host-192-168-3-6 tarena]#python adduser.py
username: alice
Changing password for user alice.
passwd: all authentication tokens updated successfully.
[root@host-192-168-3-6 tarena]# mail
Heirloom Mail version 12.5 7/5/10. Type ? for help.
"/var/spool/mail/root": 2 messages 1 new
1 root Fri Jun 16 10:31 21/691 "user info"
>N 2 root Sat Jul 29 10:03 20/710 "create user"
&
Message 2:
From root@host-192-168-3-6.localdomain Sat Jul 29 10:03:55 2017
Return-Path: <root@host-192-168-3-6.localdomain>
X-Original-To: root
Delivered-To: root@host-192-168-3-6.localdomain
Date: Sat, 29 Jul 2017 10:03:52 +0800
To: root@host-192-168-3-6.localdomain
Subject: create user
User-Agent: Heirloom mailx 12.5 7/5/10
Content-Type: text/plain; charset=us-ascii
From: root@host-192-168-3-6.localdomain (root)
Status: R
your account is created.
username: alice
password: IHgkunGZ
&
#!/usr/bin/env python
#coding:utf8
import sys
import randpass2
import os
import string
contents = """username: ${username}
password: ${password}
"""
t = string.Template(contents)
def adduser(user,passwd,email):
data = t.substitute(username=user,password=passwd)
os.system("useradd %s" % user)
os.system("echo %s| passwd --stdin %s" % (passwd,user))
os.system("echo -e '%s' | mail -s 'user info' %s" % (data,email))
if __name__ == '__main__':
username = sys.argv[1]
pwd = randpass2.gen_pass()
adduser(username,pwd,'root@localhost')
执行结果:
[root@host-192-168-3-6 test]# chmod +x adduser.py [root@host-192-168-3-6 test]# ./adduser.py jerry Changing password for user jerry. passwd: all authentication tokens updated successfully.
注意:randpass2模块是自定义的模块,其中的内容为:
#coding:utf8
import random
import string
all_chs = string.letters + string.digits
def gen_pass(num=8):
pwd = ''
for i in range(num):
ch = random.choice(all_chs)
pwd += ch
return pwd
if __name__ == "__main__":
print gen_pass(5)
print gen_pass()
print gen_pass(10)
#!/usr/bin/env python
#-*- coding:utf-8 -*-
stack = []
def pushit(): #定义压栈函数
item = raw_input('input item: ').strip()
stack.append(item)
def popit(): #定义出栈函数
if len(stack) == 0:
print '\033[32;1mEmpty stack.\033[0m'
else:
print '\033[32;1mpoped [' + stack.pop() + ']\033[0m'
def viewstack(): #定义查看函数
print '\033[32;1m', stack, '\033[0m'
CMDs = {'p':pushit, 'o':popit, 'v':viewstack} #将函数存储在字典中
def showmenu():
prompt = """(P)ush
p(O)p
(V)iew
(Q)uit
Please input your choice: """
while True:
try:
choice = raw_input(prompt).strip().lower()[0]
except (KeyboardInterrupt, EOFError):
choice = 'q'
if choice not in 'povq':
print 'Invalid input. Try again.'
continue
if choice == 'q':
break
else:
CMDs[choice]() #执行字典中对应的函数
if __name__ == '__main__':
showmenu()
(P)ush p(O)p (V)iew (Q)uit Please input your choice: p input item: hello (P)ush p(O)p (V)iew (Q)uit Please input your choice: p input item: world (P)ush p(O)p (V)iew (Q)uit Please input your choice: v ['hello', 'world'] (P)ush p(O)p (V)iew (Q)uit Please input your choice: o poped [world] (P)ush p(O)p (V)iew (Q)uit Please input your choice: q
#!/usr/bin/env python
#coding:utf8
stack = []
def pushit():
item = raw_input("item: ")
stack.append(item)
def popit():
if stack:
print "poped item:",stack.pop()
else:
"Empty stack"
def viewit():
print stack
def show_menu():
CMDs = {'0':pushit,'1':popit,'2':viewit}
prompt ='''(0) push it
(1) pop it
(2) view it
(3) quit
Please input your choice(0/1/2/3):'''
while True:
choice = raw_input(prompt).strip()[0]
if choice not in '0123':
print "Invalid input,Try again."
continue
if choice == '3':
break
CMDs[choice]()
if __name__ == "__main__":
show_menu()
#!/usr/bin/env python
#coding:utf8
#whitespace = '\t\n\v\r\f'
from string import whitespace
def lrmsps(astr):
if not astr:
return astr
for i in range(len(astr)):
if astr[i] not in whitespace:
break
else:
return ''
return astr[i:]
def rrmsps(astr):
if not astr:
return astr
for i in range(-1,-(len(astr)+1),-1):
if astr[i] not in whitespace:
break
else:
return ''
return astr[:(i+1)]
def rmsps(astr):
return rrmsps(lrmsps(astr))
if __name__ == '__main__':
hi = " hello \t"
print "|%s|" % lrmsps(hi)
print "|%s|" % rrmsps(hi)
print "|%s|" % rmsps(hi)
执行结果:
|hello | | hello| |hello|
rmsps2.py内容:
#!/usr/bin/env python
#coding:utf8
from string import whitespace
def lrmsps(astr):
str_list = list(astr)
for i in range(len(str_list)):
if str_list[0] not in whitespace:
break
str_list.pop(0)
return ''.join(str_list)
def rrmsps(astr):
str_list = list(astr)
for i in range(len(str_list)):
if str_list[-1] not in whitespace:
break
str_list.pop()
return ''.join(str_list)
def rmsps(astr):
return lrmsps(rrmsps(astr))
if __name__ == '__main__':
hi = ' hello \t'
print "|%s|" % lrmsps(hi)
print "|%s|" % rrmsps(hi)
print "|%s|" % rmsps(hi)
执行结果:
|hello | | hello| |hello|
convertip.py内容:
#!/usr/bin/env python
#coding:utf8
def int2ip(num):
ip_list = []
for i in range(4):
num,mod = divmod(num, 256)
ip_list.insert(0,str(mod))
return '.'.join(ip_list)
def ip2int(ip):
ip_list = ip.split('.')
num = 0
for i in range(len(ip_list)):
num += int(ip_list[i]) * 256 ** (3-i)
return num
if __name__ == "__main__":
print int2ip(3232235786)
print ip2int('192.168.1.10')
执行结果:
192.168.1.10 3232235786
用户登陆信息系统 编写 ulogin.py 脚本,主要要求如下: 1、使用字典模拟一个用户登陆信息系统 2、支持新用户注册,新用户名和密码注册到字典中 3、支持老用户登陆,用户名和密码正确提示登陆成功 4、主程序通过循环询问进行何种操作,根据用户的选择,执行注册或是登陆操作
方案 因为没有永久存储,不能把用户名和密码永久保存下来,所以在编写程序时,应该使用循环结构保证程序不要退出。 在字典里,将 key 设置为用户名,value 设置为密码
方法1:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import getpass
db = {} #定义用于用户信息的字典
def newUser(): #定义新用户注册函数
username = raw_input('username: ')
if username in db:
print "\033[32;1m%s alread exists!\033[0m" % username
else:
password = getpass.getpass()
db[username] = password
def oldUser(): #定义老用户登陆函数
username = raw_input('username: ')
password = getpass.getpass() #不在屏幕上显示密码
if username in db:
if db[username] == password:
print '\033[32;1mlogin successful!\033[0m'
else:
print '\033[32;1mlogin incorrect.\033[0m'
else:
print '\033[32;1mlogin incorrect.\033[0m'
CMDs = {'n': newUser, 'o': oldUser} #将函数存放在字典中
def showMenu():
prompt = """(N)ew user
(O)ld user
(Q)uit
please input your choice: """
while True:
try:
choice = raw_input(prompt).strip()[0].lower()
except (KeyboardInterrupt, EOFError):
choice = 'q'
if choice not in 'noq':
print '\033[31;1mInvalid option.Try again(n / o / q).\033[0m'
continue
if choice == 'q':
break
CMDs[choice]()
if __name__ == '__main__':
showMenu()
[root@host-192-168-3-6 tarena]# python ulogin.py (N)ew user (O)ld user (Q)uit please input your choice: n username: tom Password: (N)ew user (O)ld user (Q)uit please input your choice: n username: tom tom alread exists! (N)ew user (O)ld user (Q)uit please input your choice: o username: tom Password: login successful! (N)ew user (O)ld user (Q)uit please input your choice: q
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import getpass
db = {}
def new_user():
user = raw_input("username: ")
pwd = raw_input("password: ")
# if user not in db:
# db[user] ==pwd
if pwd == db.setdefault(user,pwd):
print "Register successful"
else:
print "%s already exists." % user
def olduser():
user = raw_input("username: ")
pwd = getpass.getpass("password: ")
#if user not in db or db[user] != pwd:
if db.get(user) != pwd:
print "Login incorrect."
else:
print "Login successful."
def show_menu():
CMDs = {'0':new_user,'1':olduser}
prompt = """(0)new user
(1)old user
(2)quit
Please input your choice(0/1/2):"""
while True:
choice = raw_input(prompt).strip()[0]
if choice not in '012':
print "Invalid choice.Try again.."
continue
if choice == '2':
break
CMDs[choice]()
if __name__ == "__main__":
show_menu()
[root@host-192-168-3-6 tarena]# python ulogin2.py (0)new user (1)old user (2)quit Please input your choice(0/1/2):0 username: tom password: 123456 Register successful (0)new user (1)old user (2)quit Please input your choice(0/1/2):1 username: tom password: Login successful. (0)new user (1)old user (2)quit Please input your choice(0/1/2):q Invalid choice.Try again.. (0)new user (1)old user (2)quit Please input your choice(0/1/2):2
#!/usr/bin/env python
db = {'create' : 'create', 'delete' : 'delete', 'modify' : 'modify'}
prompt = """create
delete
modify
please input your choice: """
choice = raw_input(prompt)
if db.get(choice):
print db[choice], 'user'
else:
print 'input error'
执行结果:
create delete modify please input your choice: create create user
方法2:
#!/usr/bin/env python
#coding:utf8
import sys
ops = ['create','modify','delete']
op = sys.argv[1]
if op in ops:
print "%s user" % op
else:
print "Usage: create | modify | delete user"
执行结果:
[root@host-192-168-3-6 tarena]# chmod +x case.py [root@host-192-168-3-6 tarena]# ./case.py tom Usage: create | modify | delete user
实现系统中unix2dos命令的功能
方法1:
#!/usr/bin/env python
#coding:utf8
import os
import sys
def unix2dos(fname):
dfname = os.path.splitext(fname)[0] + '.win'
src_fobj = open(fname)
dst_fobj = open(dfname,'w')
for line in src_fobj:
dst_fobj.write(line.rstrip('\n\r') + '\r\n')
src_fobj.close()
dst_fobj.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: %s filename " % sys.argv[0]
sys.exit(1)
filename = sys.argv[1]
if not os.path.isfile(filename):
print "No such file: %s" % filename
sys.exit(2)
unix2dos(filename)
{root@host-192-168-3-6 test]# python u2d.py
Usage: u2d.py filename
[root@host-192-168-3-6 test]# vim abc.txt
abcdeef
hello
[root@host-192-168-3-6 test]# python u2d.py abc.txt
[root@host-192-168-3-6 test]# ls
abc.txt
abc.win
#!/usr/bin/env python
#coding:utf8
import sys
def unix2dos(fname,sep='\r\n'):
dst_name = fname + '.txt'
with open(fname) as src_fobj:
with open(dst_name,'w') as dst_fobj:
for line in src_fobj:
dst_fobj.write("%s%s" % (line.rstrip('\r\n'),sep))
if __name__ == "__main__":
unix2dos(sys.argv[1])
[root@host-192-168-3-6 ~]# python u2d.py myadd.py
root@host-192-168-3-6 ~]# ls
myadd.py
myadd.py.txt
u2d.py
>>> with open('myadd.py') as f1:
... f1.readline()
...
'#!/usr/bin/env python\n'
>>> with open('myadd.py.txt') as f1:
... f1.readline()
...
'#!/usr/bin/env python\r\n'
>>>
#!/usr/bin/env python
#coding:utf8
import os
import sys
def dos2unix(fname):
dfname = os.path.splitext(fname)[0] + '.unix'
src_fobj = open(fname)
dst_fobj = open(dfname,'w')
for line in src_fobj:
dst_fobj.write(line.rstrip('\n\r') + '\n')
src_fobj.close()
dst_fobj.close()
if __name__ == '__main__':
if len(sys.argv) != 2:
print "Usage: %s filename " % sys.argv[0]
sys.exit(1)
filename = sys.argv[1]
if not os.path.isfile(filename):
print "No such file: %s" % filename
sys.exit(2)
dos2unix(filename)
#!/usr/bin/env python
#coding:utf8
import sys
import u2d
from functools import partial
dos2unix = partial(u2d.unix2dos,sep = '\n')
if __name__ == '__main__':
dos2unix(sys.argv[1])
[root@host-192-168-3-6 ~]# python d2u.py myadd.py.txt
[root@host-192-168-3-6 ~]# ls
myadd.py
myadd.py.txt
d2u.py
myadd.py.txt.txt
u2d.py
>>> with open('myadd.py.txt.txt') as f3:
... f3.readline()
...
'#!/usr/bin/env python\n'
>>>
#!/usr/bin/env python
#coding:utf-8
from operator import add, sub
from random import randint, choice
ops = {'+': add, '-': sub} #将 add 和 sub 函数放到字典中
MAXTRIES = 2
def doprob():
op = choice('+-')
nums = [randint(1, 100) for i in range(2)] #使用列表解析,生成数字列表
nums.sort(reverse = True) #将列表按降序方式排序
ans = ops[op](*nums) #此处*nums 用于将列表解开,得到数字
pr = '%d %s %d = ' % (nums[0], op, nums[1])
oops = 0 #定义错误计数器
while True:
try:
if int(raw_input(pr)) == ans:
print 'correct'
break
if oops == MAXTRIES:
print 'answer\n%s%d' % (pr, ans)
break
else:
print 'incorrect... try again.'
oops += 1
except (KeyboardInterrupt, EOFError, ValueError):
print 'invalid input... try again.'
def main():
while True:
doprob()
try:
opt = raw_input('Again?[y]?').lower()
if opt and opt[0] == 'n':
break
except (KeyboardInterrupt, EOFError):
break
if __name__ == '__main__':
main()
方法1:
执行结果:
[root@host-192-168-3-6 tarena]# python mathgame.py 36 - 29 = 7 correct Again?[y]?n
方法2:
#!/usr/bin/env python
#coding:utf8
import random
def add(x,y):
return x + y
def sub(x,y):
return x - y
def probe():
CMDs = {'+':add,'-':sub}
nums = [random.randint(1,50) for i in range(2)]
nums.sort(reverse=True)
op = random.choice('+-')
answer = CMDs[op](*nums)
prompt = "%s%s%s = " % (nums[0],op,nums[1])
tries = 0
while tries <3:
result = int(raw_input(prompt))
if answer == result:
print "Very Good!!!"
break
print "Wrong answer..."
tries += 1
else:
print "\033[31;1m%s%s\033[0m" % (prompt,answer)
if __name__ == "__main__":
while True:
probe()
yn = raw_input("Continue(y/n)? ").strip()[0]
if yn in 'nN':
break
执行结果:
39-25 = 14 Very Good!!! Continue(y/n)? n
方法3:
#!/usr/bin/env python
#coding:utf8
import random
def add(x,y):
return x + y
def sub(x,y):
return x - y
def probe():
CMDs = {'+':add,'-':sub}
nums = [random.randint(1,50) for i in range(2)]
nums.sort(reverse=True)
op = random.choice('+-')
answer = CMDs[op](*nums)
prompt = "%s%s%s = " % (nums[0],op,nums[1])
tries = 0
while tries <3:
try:
result = int(raw_input(prompt))
except:
continue
if answer == result:
print "Very Good!!!"
break
print "Wrong answer..."
tries += 1
else:
print "\033[31;1m%s%s\033[0m" % (prompt,answer)
if __name__ == "__main__":
while True:
probe()
try:
yn = raw_input("Continue(y/n)? ").strip()[0]
except (KeyboardInterrupt,EOFError):
print "\nBye Bye"
yn = 'n'
except IndexError:
continue
if yn in 'nN':
break
29+13 = 42 Very Good!!! Continue(y/n)? 123 42-29 = 13 Very Good!!! Continue(y/n)? y 32-4 = 28 Very Good!!! Continue(y/n)? n
#!/usr/bin/env python
#coding:utf8
import random
'''
def add(x,y):
return x + y
def sub(x,y):
return x - y
'''
def probe():
#CMDs = {'+':add,'-':sub}
CMDs = {'+':lambda x,y:x+y,'-':lambda x,y:x-y}
nums = [random.randint(1,50) for i in range(2)]
nums.sort(reverse=True)
op = random.choice('+-')
answer = CMDs[op](*nums)
prompt = "%s%s%s = " % (nums[0],op,nums[1])
tries = 0
while tries <3:
try:
result = int(raw_input(prompt))
except:
continue
if answer == result:
print "Very Good!!!"
break
print "Wrong answer..."
tries += 1
else:
print "\033[31;1m%s%s\033[0m" % (prompt,answer)
if __name__ == "__main__":
while True:
probe()
try:
yn = raw_input("Continue(y/n)? ").strip()[0]
except (KeyboardInterrupt,EOFError):
print "\nBye Bye"
yn = 'n'
except IndexError:
continue
if yn in 'nN':
break
执行结果:
38-12 = 26 Very Good!!! Continue(y/n)? n
func1.py内容:
!/usr/bin/env python
#coding:utf8
def func1(x):
return x % 2
def func2(x):
return x **2
def func3(x,y):
return x + y
if __name__ == "__main__":
print filter(func1,range(1,11))
print filter(lambda x:x %2,range(1,11))
print map(func2,range(1,11))
print map(lambda x: x**2,range(1,11))
print reduce(func3,range(1,11))
print reduce(lambda x,y: x+y,range(1,11))
[1, 3, 5, 7, 9] [1, 3, 5, 7, 9] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 55 55
[root@host-192-168-3-6 ~]# cd /home/
[root@host-192-168-3-6 home]# mkdir -p demo/{aaa/bbb,ccc}
[root@host-192-168-3-6 home]# ls
centos demo jerry list mytouch zhuji
[root@host-192-168-3-6 home]# ls demo/
aaa ccc
[root@host-192-168-3-6 home]# ls demo/aaa/
bbb
[root@host-192-168-3-6 home]# cp /etc/hosts demo/
[root@host-192-168-3-6 home]# touch demo/d.txt
[root@host-192-168-3-6 home]# touch demo/aaa/{a1,a2}.txt
[root@host-192-168-3-6 home]# ls demo/aaa/
a1.txt a2.txt bbb
[root@host-192-168-3-6 home]# touch demo/aaa/bbb/b.txt
[root@host-192-168-3-6 home]# touch demo/ccc/{c1,c2}.txt
[root@host-192-168-3-6 home]# ls -R demo/
demo/:
aaa ccc d.txt hosts
demo/aaa:
a1.txt a2.txt bbb
demo/aaa/bbb:
b.txt
demo/ccc:
c1.txt c2.txt
[root@host-192-168-3-6 home]#
#!/usr/bin/env python
#coding:utf8
import os
import sys
def lsdir(folder):
contents = os.listdir(folder)
print "%s:\n%s\n" % (folder,contents)
for item in contents:
full_path = os.path.join(folder,item)
if os.path.isdir(full_path):
lsdir(full_path)
if __name__ == "__main__":
lsdir(sys.argv[1])
[root@host-192-168-3-6 ~]# python lsdir.py /home/demo/ /home/demo/: ['aaa', 'ccc', 'hosts', 'd.txt'] /home/demo/aaa: ['bbb', 'a1.txt', 'a2.txt'] /home/demo/aaa/bbb: ['b.txt'] /home/demo/ccc: ['c2.txt', 'c1.txt']
> import os
>>> import tab
>>> os.wa
os.wait( os.wait3( os.wait4( os.waitpid( os.walk(
>>> os.walk('/home/demo')
<generator object walk at 0x7ff99ff2eeb0>
>>> list(os.walk('/home/demo'))
[('/home/demo', ['aaa', 'ccc'], ['hosts', 'd.txt']), ('/home/demo/aaa', ['bbb'], ['a1.txt', 'a2.txt']), ('/home/demo/aaa/bbb', [], ['b.txt']), ('/home/demo/ccc', [], ['c2.txt', 'c1.txt'])]
>>> a = os.walk('/home/demo')
>>> a.next()
('/home/demo', ['aaa', 'ccc'], ['hosts', 'd.txt'])
>>> a.next()
('/home/demo/aaa', ['bbb'], ['a1.txt', 'a2.txt'])
>>> a.next()
('/home/demo/aaa/bbb', [], ['b.txt'])
>>> a.next()
('/home/demo/ccc', [], ['c2.txt', 'c1.txt'])
>>> a.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
#!/usr/bin/env python
#coding:utf8
import os
import sys
def lsdir(folder):
for path,dirs,files in os.walk(folder):
print "%s:\n%s\n" % (path,(dirs + files))
if __name__ == "__main__":
lsdir(sys.argv[1])
[root@host-192-168-3-6 ~]# python lsdir2.py /home/demo/ /home/demo/: ['aaa', 'ccc', 'hosts', 'd.txt'] /home/demo/aaa: ['bbb', 'a1.txt', 'a2.txt'] /home/demo/aaa/bbb: ['b.txt'] /home/demo/ccc: ['c2.txt', 'c1.txt']
#!/usr/bin/env python
#coding:utf8
def cp():
sfname = '/bin/ls'
dfname = '/root/ls'
src_fobj = open(sfname)
dst_fobj = open(dfname,'w')
while True:
data = src_fobj.read(4096)
if not data:
break
dst_fobj.write(data)
src_fobj.close()
dst_fobj.close()
cp()
cp.py带参数:
#!/usr/bin/env python
#coding:utf8
def cp(sfname,dfname):
src_fobj = open(sfname)
dst_fobj = open(dfname,'w')
while True:
data = src_fobj.read(4096)
if not data:
break
dst_fobj.write(data)
src_fobj.close()
dst_fobj.close()
cp('/bin/ls','/home/list')
cp('/bin/touch','/home/mytouch')
cd /home/ [root@host-192-168-3-6 home]# ls centos [root@host-192-168-3-6 home]# cd centos/ [root@host-192-168-3-6 test]# python zgy.py [root@host-192-168-3-6 test]# cd - /home [root@host-192-168-3-6 home]# ls centos list mytouch
#!/usr/bin/env python
#coding:utf8
import sys
def cp(sfname,dfname):
src_fobj = open(sfname)
dst_fobj = open(dfname,'w')
while True:
data = src_fobj.read(4096)
if not data:
break
dst_fobj.write(data)
src_fobj.close()
dst_fobj.close()
cp(sys.argv[1],sys.argv[2])
[root@host-192-168-3-6 test]# python cp.py /etc/hosts hosts hosts.allow hosts.deny [root@host-192-168-3-6 test]# python zgy.py /etc/hosts /home/zhuji [root@host-192-168-3-6 test]# cd /home/ [root@host-192-168-3-6 home]# cat zhuji 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 [root@host-192-168-3-6 home]#
练习:利用cPickle模块
编写一个家庭理财系统。记录你的收支情况。首先,假设你有1万存款,以它作为基数,存钱、花钱都要明确的记录。
时间 存钱 花钱 余额 备注
分析:
1、需要两个记录文件,一个文件当成钱包文件(balance.txt),里面存放着你的最新余额,另一个是记帐本文件(record.txt)
2、为了每次测试方便,使用一个初始化文件(init_money.py),向钱包文件中写入10000
3、主程序文件(finance.py),要有四个基础函数,一个用于存钱(saveMoney),一个用于花钱(spendMoney),一个用于记帐(logger),一个用于查询(queryInfo)
4、主程序运行时,打印一个菜单,询问用户要做什么。获取用户行为后,调用相应的函数。
方法1:
step1:
root@host-192-168-3-6 ~]# cd tarena/ [root@host-192-168-3-6 tarena]# mkdir test [root@host-192-168-3-6 tarena]# cd test [root@host-192-168-3-6 test]# ls initm.py
initm.py内容:
#!/usr/bin/env python
import cPickle as p
fd = file('balance.txt', 'w')
p.dump(10000, fd)
fd.close()
fobj = file('record.txt', 'w')
fobj.close()
执行initm.py
[root@host-192-168-3-6 test]# python initm.py [root@host-192-168-3-6 test]# ls balance.txt initm.py record.txt [root@host-192-168-3-6 test]# vim balance.txt I10000
step2:新建finance.py
#!/usr/bin/env python
import sys
import cPickle as p
def spendMoney():
spend_date = raw_input('time: ')
spend_money = int(raw_input('how much: '))
spend_comment = raw_input('detail: ')
fd = file('balance.txt')
balance = p.load(fd)
fd.close()
balance -= spend_money
fd = file('balance.txt', 'w')
p.dump(balance, fd)
fd.close()
logger(spend_date, spend_comment, balance, spend_money)
def saveMoney():
save_date = raw_input('time: ')
save_money = int(raw_input('how much: '))
save_comment = raw_input('detail: ')
fd = file('balance.txt')
balance = p.load(fd)
fd.close()
balance += save_money
fd = file('balance.txt', 'w')
p.dump(balance, fd)
fd.close()
logger(save_date, save_comment, balance, amount_save = save_money)
def queryInfo():
fobj = file('record.txt')
print "%-15s%-8s%-8s%-8s%-30s" % ('time', 'kaixiao', 'save', 'balance', 'detail')
for eachLine in fobj:
print eachLine,
fobj.close()
def logger(log_time, comment, new_balance, amount_spend = '', amount_save = ''):
fd = file('record.txt', 'a')
fd.write('%-15s%-8s%-8s%-8s%-30s\n' % (log_time, amount_spend, amount_save, new_balance, comment))
fd.close()
CMDs = {'s': spendMoney, 'v':saveMoney, 'q':queryInfo}
def main():
prompt = """\033[32;1m(S)pend money
sa(V)e money
(Q)uery infomation
(E)xit
Enter your choice: \033[0m"""
while True:
while True:
choice = raw_input(prompt).strip()[0].lower()
if choice not in 'svqe':
print 'invalid input. try again(s v q e).'
continue
else:
break
if choice == 'e':
sys.exit()
else:
CMDs[choice]()
if __name__ == '__main__':
main()
root@host-192-168-3-6 test]# python finance.py (S)pend money sa(V)e money (Q)uery infomation (E)xit Enter your choice: v time: 2017-07-31 how much: 2000 detail: abc (S)pend money sa(V)e money (Q)uery infomation (E)xit Enter your choice: q time kaixiao save balance detail 2017-07-31 2000 12000 abc (S)pend money sa(V)e money (Q)uery infomation (E)xit Enter your choice: s time: 2017-07-31 how much: 1000 detail: shopping (S)pend money sa(V)e money (Q)uery infomation (E)xit Enter your choice: q time kaixiao save balance detail 2017-07-31 2000 12000 abc 2017-07-31 1000 11000 shopping (S)pend money sa(V)e money (Q)uery infomation (E)xit Enter your choice: e [root@host-192-168-3-6 test]#
#!/usr/bin/env python
import cPickle as p
with open('record.txt', 'w') as record:
pass
with open('balance.txt', 'w') as f:
p.dump(10000, f)
执行initm.py
[root@host-192-168-3-6 test]# python initm.py [root@host-192-168-3-6 test]# ls balance.txt initm.py record.txt [root@host-192-168-3-6 test]# vim balance.txt I10000
step2:新建finance.py
#!/usr/bin/env python
#coding:utf-8
import sys
import time
import cPickle as p
walletfile = '/root/tarena/test/balance.txt' #绝对路径下的文件
recordfile = '/root/tarena/test/record.txt'
def spendMoney():
amount = int(raw_input('数额:'))
comment = raw_input('用途:')
with file(walletfile) as f:
newbalance = p.load(f) - amount
with file(walletfile,'w') as f:
p.dump(newbalance,f)
logger('',amount,newbalance,comment)
def saveMoney():
amount = int(raw_input('数额:'))
comment = raw_input('来源:')
with file(walletfile) as f:
newbalance = p.load(f) + amount
with file(walletfile,'w') as f:
p.dump(newbalance,f)
logger(amount,'',newbalance,comment)
def queryInfo():
print "%-14s%-9s%-9s%-9s%-19s" % ('时间','存入','支出','余额','备注')
with file(recordfile) as f:
for eachLine in f:
print eachLine,
def logger(saM,spM,nb,cm):
result = "%-12s%-7s%-7s%-7s%-17s\n" % (time.strftime('%Y-%m-%d'),saM,spM,nb,cm)
with file(recordfile,'a') as f:
f.write(result)
CMDs = {'s': spendMoney, 'v':saveMoney, 'q':queryInfo}
def showmenu():
prompt = """(s)支出
(v)收入
(q)查询
(e)退出
请输入您的选择(s/v/q/e): """
while True:
choice = raw_input(prompt).strip()[0].lower()
if choice not in 'svqe':
print '\033[31;1m无效的选择,请重试.\033[0m'
continue
if choice == 'e':
break
else:
CMDs[choice]()
if __name__ == '__main__':
showmenu()
[root@host-192-168-3-6 test]# python finance.py (s)支出 (v)收入 (q)查询 (e)退出 请输入您的选择(s/v/q/e): q 时间 存入 支出 余额 备注 (s)支出 (v)收入 (q)查询 (e)退出 请输入您的选择(s/v/q/e): v 数额:10000 来源:abc (s)支出 (v)收入 (q)查询 (e)退出 请输入您的选择(s/v/q/e): q 时间 存入 支出 余额 备注 2017-07-31 10000 20000 abc (s)支出 (v)收入 (q)查询 (e)退出 请输入您的选择(s/v/q/e): s 数额:1000 用途:shopping (s)支出 (v)收入 (q)查询 (e)退出 请输入您的选择(s/v/q/e): q 时间 存入 支出 余额 备注 2017-07-31 10000 20000 abc 2017-07-31 1000 19000 shopping (s)支出 (v)收入 (q)查询 (e)退出 请输入您的选择(s/v/q/e): e [root@host-192-168-3-6 test]#
#!/usr/bin/env python
#coding:utf8
import os
import cPickle as p
import time
def spend_money(wallet,record,date,amount,comment):
with open(wallet) as fobj:
balance = p.load(fobj) - amount
with open(wallet,'w') as fobj:
p.dump(balance,fobj)
with open(record,'a') as fobj:
fobj.write(
"%-12s%-8s%-8s%-10s%-20s\n" % (date,amount,'N/A',balance,comment)
)
def save_money(wallet,record,date,amount,comment):
with open(wallet) as fobj:
balance = p.load(fobj) + amount
with open(wallet,'w') as fobj:
p.dump(balance,fobj)
with open(record,'a') as fobj:
fobj.write(
"%-12s%-8s%-8s%-10s%-20s\n" % (date,'N/A',amount,balance,comment)
)
def query_money(wallet,record):
print "%-12s%-8s%-8s%-10s%-20s\n" % \
('date','spend','save','balance','comment')
with open(record) as fobj:
for line in fobj:
print line,
with open(wallet) as fobj:
print "New Balance: \n%s" % p.load(fobj)
def show_menu(wallet,record):
CMDs = {'0':spend_money,'1':save_money,'2':query_money}
prompt = """(0)spend money
(1)save money
(2)query money
(3)quit
Please input your choice(0/1/2/3):"""
while True:
try:
choice = raw_input(prompt).strip()[0]
except IndexError:
continue
except (KeyboardInterrupt,EOFError):
choice = '3'
if choice not in '0123':
print "Invalid choice ,Try again"
continue
if choice == '3':
print "Bye-bye"
break
args = (wallet,record)
if choice in '01':
date = time.strftime("%Y%m%d")
try:
amount = int(raw_input("amount: "))
comment = raw_input("comment: ")
except ValueError:
print "Invalid number.Try again."
continue
except (KeyboardInterrupt,EOFError):
print "\nBye-bye"
break
args = (wallet,record,date,amount,comment)
CMDs[choice](*args)
if __name__ == "__main__":
wallet = 'wallet.data'
record = "record.txt"
if not os.path.exists(wallet):
with open(wallet,'w') as fobj:
p.dump(10000, fobj)
if not os.path.exists(record):
os.mknod(record)
show_menu(wallet,record)
[root@host-192-168-3-6 test]# ls finance.py [root@host-192-168-3-6 test]# python finance.py (0)spend money (1)save money (2)query money (3)quit Please input your choice(0/1/2/3):1 amount: 10000 comment: abc (0)spend money (1)save money (2)query money (3)quit Please input your choice(0/1/2/3):2 date spend save balance comment 20170801 N/A 10000 20000 abc New Balance: 20000 (0)spend money (1)save money (2)query money (3)quit Please input your choice(0/1/2/3):0 amount: 1000 comment: shopping (0)spend money (1)save money (2)query money (3)quit Please input your choice(0/1/2/3):q Invalid choice ,Try again (0)spend money (1)save money (2)query money (3)quit Please input your choice(0/1/2/3):2 date spend save balance comment 20170801 N/A 10000 20000 abc 20170801 1000 N/A 19000 shopping New Balance: 19000 (0)spend money (1)save money (2)query money (3)quit Please input your choice(0/1/2/3):3 Bye-bye [root@host-192-168-3-6 test]# ls finance.py record.txt wallet.data [root@host-192-168-3-6 test]#
#!/usr/bin/env python
#coding:utf-8
import time
import hashlib
import tarfile
import os
import cPickle
basedir = '/home/demo'
srcdir = 'src'
dstdir = 'dst'
md5file = os.path.join(basedir, dstdir, 'md5.data') #md5 文件位置
fullname = 'full_src%s.tar.gz' % (time.strftime('%Y%m%d')) #完全备份文件名
incname = 'incr_src%s.tar.gz' % (time.strftime('%Y%m%d')) #增量备份文件名
def fullBackup(): #完全备份函数
os.chdir(basedir)
tar = tarfile.open(os.path.join(basedir, dstdir, fullname), 'w:gz')
tar.add(srcdir)
tar.close()
md5dict = {} #计算文件 md5 值
for eachFile in os.listdir(os.path.join(basedir, srcdir)):
fullpath = os.path.join(basedir, srcdir, eachFile)
md5dict[eachFile] = md5sum(fullpath)
with open(md5file, 'w') as f: #存储文件 md5 值到 cPicle 存储器
cPickle.dump(md5dict, f)
def incrBackup(): #增量备份函数
with open(md5file) as f:
storedmd5 = cPickle.load(f)
newmd5 = {}
for eachFile in os.listdir(os.path.join(basedir, srcdir)):
fullpath = os.path.join(basedir, srcdir, eachFile)
newmd5[eachFile] = md5sum(fullpath)
tar = tarfile.open(os.path.join(basedir, dstdir, incname), 'w:gz')
os.chdir(basedir)
for eachKey in newmd5:
if (eachKey not in storedmd5) or (newmd5[eachKey] != storedmd5[eachKey]):
tar.add(os.path.join(srcdir, eachKey))
tar.close()
with open(md5file, 'w') as f:
cPickle.dump(newmd5, f)
def md5sum(fname): #md5 值计算函数
m = hashlib.md5()
with open(fname) as f:
while True:
data = f.read(4096)
if len(data) == 0:
break
m.update(data)
return m.hexdigest()
def main():
if time.strftime('%a') == 'Mon': #如果是周一执行完全备份,否则执行增量备份
fullBackup()
else:
incrBackup()
if __name__ == '__main__':
main()
[root@host-192-168-3-6 test]# mkdir /home/demo/ [root@host-192-168-3-6 test]# cd /home/demo/ [root@host-192-168-3-6 demo]# mkdir dst [root@host-192-168-3-6 demo]# mkdir src [root@host-192-168-3-6 demo]# cd - /root/tarena/test [root@host-192-168-3-6 test]# [root@host-192-168-3-6 test]# python backup.py [root@host-192-168-3-6 test]# ls backup.py finance.py record.txt wallet.data [root@host-192-168-3-6 test]# cd /home/demo/ [root@host-192-168-3-6 demo]# ls aaa ccc dst d.txt hosts passwd redhat-release shadow src [root@host-192-168-3-6 demo]# cd src/ [root@host-192-168-3-6 src]# ls [root@host-192-168-3-6 src]# cd ../dst/ [root@host-192-168-3-6 dst]# ls full_src20170801.tar.gz md5.data [root@host-192-168-3-6 dst]#
step3:测试脚本执行
[root@py01 bin]# crontab –e 00 01 * * * /root/bin/backup.py
方法2:
step1:
>>> afile = "/home/demo/aaa/a.txt"
>>> afile.split('/home')
['', '/demo/aaa/a.txt']
>>> afile.split("home")[1]
'/demo/aaa/a.txt'
>>> afile.split("home")[1].lstrip('/')
'demo/aaa/a.txt'
>>>
#!/usr/bin/env python
#coding:utf8
import time
import os
import tarfile
import cPickle as p
import hashlib
def check_md5(fname):
#计算文件md5值,为了防止文件太大,占用内存,每次计算4096字节
m = hashlib.md5()
with open(fname) as fobj:
while True:
data = fobj.read(4096)
if not data:
break
m.update(data)
return m.hexdigest()
def full_backup(src_dir,dst_dir,md5file):
"""首先,切割源目录,将要备份的目录及其所在的目录分开
目标名称:demo_full_20160411.tar.gz,再生成绝对路径
"""
md5dict = {}
base_dir,back_dir = os.path.split(src_dir.rstrip('/'))
back_name = "%s_full_%s.tar.gz" % (back_dir,time.strftime("%Y%m%d"))
full_path = os.path.join(dst_dir,back_name)
os.chdir(base_dir)
tar = tarfile.open(full_path,"w:gz")
tar.add(back_dir)
tar.close()
for path,dirs,files in os.walk(src_dir):
for each_file in files:
full_name = os.path.join(path,each_file)
md5dict[full_name] = check_md5(full_name)
with open(md5file,'w') as fobj:
p.dump(md5dict,fobj)
def incr_backup(src_dir,dst_dir,md5file):
base_dir,back_dir = os.path.split(src_dir.rstrip('/'))
back_name = "%s_incr_%s.tar.gz" % (back_dir,time.strftime("%Y%m%d"))
full_path = os.path.join(dst_dir,back_name)
new_md5 = {}
with open(md5file) as fobj:
old_md5 = p.load(fobj)
for path,dirs,files in os.walk(src_dir):
for each_file in files:
full_name = os.path.join(path,each_file)
new_md5[full_name] = check_md5(full_name)
with open(md5file,'w') as fobj:
p.dump(new_md5,fobj)
os.chdir(base_dir)
tar = tarfile.open(full_path,'w:gz')
for key in new_md5:
#if key not in old_md5 or new_md5[key] != old_md5[key]:
if old_md5.get(key) != new_md5[key]:
#key值是文件名,如果文件名不在老字典中,是新文件;如果value不一样,是改动的文件
tar.add(key.split(base_dir)[1].lstrip('/'))
tar.close()
if __name__ == "__main__":
src_dir = '/home/demo'
dst_dir = '/home/dst'
md5file = '/home/dst/md5.data'
if time.strftime('%a') == "Mon":
full_backup(src_dir,dst_dir,md5file)
else:
incr_backup(src_dir,dst_dir,md5file)
[root@host-192-168-3-6 test]# cd - /home [root@host-192-168-3-6 home]# mkdir dst [root@host-192-168-3-6 home]# mkdir demo [root@host-192-168-3-6 home]# cd - /root/tarena/test [root@host-192-168-3-6 test]# python backup.py [root@host-192-168-3-6 test]# cd - /home [root@host-192-168-3-6 home]# ls demo dst [root@host-192-168-3-6 home]# cd dst/ [root@host-192-168-3-6 dst]# ls demo_full_20170801.tar.gz md5.data
step4:修改脚本
把
if time.strftime('%a') == "Mon":
改成
if time.strftime('%a') == "Tue":
step5:执行结果
root@host-192-168-3-6 test]# python backup.py [root@host-192-168-3-6 test]# cd - /home/dst [root@host-192-168-3-6 dst]# ls demo_full_20170801.tar.gz demo_incr_20170801.tar.gz md5.data
10万+

被折叠的 条评论
为什么被折叠?



