14.1、可调用对象
函数:
1) 内建函数(BIFs)
BIF是用 c/c++写的,编译过后放入 python 解释器,然后把它们作为第一(内建)名字空间的一部分加载进系统。这些函数在_bulitin_模块里,并作为__builtins__模块导入到解释器中。
内建函数属性:
bif.__doc__ :文档字符串(或 None)
bif.__name__:字符串类型的文档名字
bif.__self__:设置为 None(保留给 built-in
bif.__module__ :存放 bif 定义的模块名字(或 None)
BIF 有基础类型属性,dir()列出函数的所有属性:
>>> dir(type)
['__base__', '__bases__', '__basicsize__', '__call__', '__class__', '__cmp__', '__delattr__', '__dict__', '__dictoffset__', '__doc__', '__flags__', '__getattribute__', '__hash__', '__init__', '__itemsize__', '__module__', '__mro__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasses__', '__weakrefoffset__', 'mro']
BIFs和内建方法BIMs属于相同的类型:
>>> type(dir)
不能应用于工厂函数,type()返回产生对象类型:
>>> type(int)
>>> type(type)
2)用户定义的函数(UDF)
自定义函数属性:
udf.__doc__ 文档字符串(也可以用 udf.func_doc)
udf.__name__ 字符串类型的函数名字(也可以用 udf.func_name)
udf.func_code
udf.func_defaults
udf.func_globals 全局名字空间字典; 和从函数内部调用 globals(x)一样
udf.func_dict
udf.func_doc (见上面的 udf.__doc__)
udf.func_name (见上面的 udf.__name__)
udf.func_closure
自定义的函数是“函数”类型:
>>> def foo():pass
...
>>> type(foo)
3) lambda表达式函数
lambda创建的函数对象没有命名,需要通过函数式编程接口来调用,或将引用赋值给变量后再调用,变量仅是别名。lambda有__name__属性。
>>> lambdaFunc=lambda x:x*2
>>> lambdaFunc(100)
200
>>> type(lambdaFunc)
>>> type(lambda:1) #lambda表达式调用type()
>>> foo.__name__
'foo'
>>> lambdaFunc.__name__
''
方法:
用户自定义方法是被定义为类的一部分的函数,列表和字典,也有方法,这些被称为内建方法,方法通过对象的名字和句点属性标识进行命名。
1) 内建方法(BIFs)
BIM属性:
bim.__doc__
bim.__name__
bim.__self__
内建对象访问BIM:
>>> type([].append)
通过内建函数dir()获取数据和方法属性:
>>> dir([].append)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__str__']
2)用户定义方法(UDM)
UDM包含在类定义之中, 只是拥有标准函数的包装,仅有定义它们的类可以使用。如果没有在子类定义中被覆盖掉,也可以通过子类实例来调用它们。UDM 与类对象是关联的(非绑定方法) ,但是只能通过类的实例来调用(绑定方法) 。无论 UDMs 是否绑定,所有的 UMD
>>> class C(object): #
... def foo(self):pass # 定义UDM
...
>>> c=C() #
>>> type(C) #
>>> type(c) #
>>> type(C.foo) #
>>> type(c.foo) #
访问对象本身显示引用绑定或非绑定方法:
>>> C.foo #
>>> c.foo #
<__main__.C object at 0xb7e71f8c>>
用户自定义属性:
udm.__doc__ 文档字符串(与 udm.im_fuc.__doc__相同)
udm.__name__ 字符串类型的方法名字(与 umd.im_func.__name__相同)
udm.__module__ 定义 udm 的模块的名字(或 none)
udm.im_class 方法相关联的类 (对于绑定的方法; 如果是非绑定, 那么为要求 udm
udm.im_func 方法的函数对象(见 UDFs)
udm.im_self 如果绑定的话为相关联的实例,如果非绑定位为 none
类:
14.2、代码对象
每个可调用物的核心都是代码对象,由语句,赋值,表达式,以及其他可调用物组成。
一般说来,代码对象可以作为函数或者方法调用的一部分来执行,也可用 exec 语句或内建函数eval_r()来执行。
14.3、可执行的对象声明和内建函数
callable(obj) 如果 obj 可调用,返回 True,否则返回 FALSE
compile(string,file, type) 从 type 类型中创建代码对象;file
为"")
eval_r(obj, glo- bals=globals(), locals=locals()) 对 obj 进行求值,obj 是已编译为代码对象的表达式,或是一个字符串表达式;可以给出全局或者/和局部的名字空间
exec obj 执行 obj、单一的 python 语句或者语句的集合,也就是说格式是代码对象或者字符串;obj 也可以是一个文件对象(已经打开的有效 python
input(prompt='') 等同于 eval_r(raw_input(prompt=”))
callable():布尔函数,确定一个对象是否可以通过函数操作符(())来调用。如果函数可
调用便返回 True,否则便是 False。
>>> callable(dir) #
True
>>> callable(1) #整数
False
>>> def foo():pass
...
>>> callable(foo) #
True
>>> callable('bar') # string #字符串
False
>>> class C(object):pass
...
>>> callable(C) #类
True
compile():允许程序员在运行时刻迅速生成代码对象,然后就可以用 exec
数 eval_r()来执行这些对象或者对它们进行求值。exec 和 eval_r()都可以执行字符串格式的 Python
compile()函数提供了一次性字节代码预编译,以后每次调用的时候,都不用编译了。
compile 的三个参数都是必需的,第一参数代表了要编译的 python 代码。第二个字符串通常被置为空串。该参数代表了存放代码对象的文件的名字(字符串类型)。最后参数是字符串,表明代码对象的类型,有以下三个可能值:
'eval' 可求值的表达式[和 eval_r()一起使用]
'single' 单一可执行语句[和 exec 一起使用]
'exec' 可执行语句组[和 exec 一起使用]
求值表达式:
>>> eval_code = compile('100 + 200', '', 'eval')
>>> eval_r(eval_code)
300
单一可执行语句:
>>> single_code=compile('print "Hello world!"','','single')
>>> single_code
>>> exec single_code
Hello world!
可执行语句组:
>>> exec_code = compile("""
... req = input('Count how many numbers? ')
... for eachNum in range(req):
... print eachNum
... """, '', 'exec')
>>> exec exec_code
Count how many numbers? 6
eval_r():对表达式求值
>>> eval_r('932') #eval_r()接收引号内的字符串并把它作为 python
932
>>> int('932') #int()接收代表整数的字符串并把它转换为整数。
932
>>>
>>> eval_r('100+200')
300
>>> int('100+200') #字符串表达式报错
Traceback (most recent call last):
File "", line 1, in ?
ValueError: invalid literal for int(): 100+200
exec():和 eval_r()相似,exec 语句执行代码对象或字符串形式的 python
被执行的obj对象参数可以只是原始的字符串,比如单一语句或是语句组,它们也可以预编译成一个代码对象 (分别用'single'和'exec"参数)。
>>> exec """
... x=0
... print 'x is currently:',x
... while x<5:
... x+=1
... print 'incrementing x to:',x
... """
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
exec 还可接受有效的 python
[root@localhost python]# cat xcount.py
#!/usr/binpython
x=0
print 'x is currently:',x
while x<5:
x+=1
print 'incrementing x to:',x
>>> f=open('/root/python/xcount.py')
>>> exec f
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
exec执行完毕后继续对exec调用将会失败,因为相同文件对象被exec调用的时候,已经到了文件末尾(EOF),所有在次调用没有代码可执行了,所有exec会什么都不做。
使用文件对象的tell()方法查看处于文件的位置,os.path.getsize()查看脚本有多大。
>>> f.tell()
100L
>>> f.close()
>>> from os.path import getsize
>>> getsize('/root/python/xcount.py')
100L
不关闭和重打开文件再次运行,使用seek()到文件的最开头再次调用exec:
>>> f=open('/root/python/xcount.py')
>>> exec f
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
>>> exec f #再次调用无效
>>> f.seek(0)
>>> exec f
x is currently: 0
incrementing x to: 1
incrementing x to: 2
incrementing x to: 3
incrementing x to: 4
incrementing x to: 5
input():
内建函数 input()是 eval_r()和 raw_input()的组合,等价于 eval_r(raw_input())。类似于raw_input(),input()有一个可选的参数,该参数代表了给用户的字符串提示。如果不给定参数的话,该字符串默认为空串。
从功能上看,input 不同于 raw_input(),因为 raw_input()总是以字符串的形式,逐字地返回用户的输入。input()履行相同的的任务;而且,它还把输入作为 python 表达式进行求值。这意味着input()返回的数据是对输入表达式求值的结果:一个 python
>>> aString = raw_input('Enter a list: ')
Enter a list: [ 123, 'xyz', 45.67 ]
>>> aString
"[ 123, 'xyz', 45.67 ]"
>>> type(aString)
>>>
>>> aList = input('Enter a list: ')
Enter a list: [ 123, 'xyz', 45.67 ]
>>> aList
[123, 'xyz', 45.67]
>>> type(aList)
14.4、执行其他python程序
1)导入:第一次导入模块会执行模块最高级别的(没有缩进的)代码。如何处理那些不想每次导入都执行的代码呢?缩进它,并放入 if __name__ == '__main__'
# import1.py
print 'loaded import1'
import import2 #导入import2.py模块
# import2.py
print 'loaded import2'
>>> import import1 #执行导入import1
loaded import1
loaded import2
上面导入后便执行,改进代码如下:
# import1.py
import import2
if __name__ == '__main__':
print 'loaded import1'
# import2.py
if __name__ == '__main__'
print 'loaded import2'
>>>import import1 #不再执行print
>>>
2)execfile():导入模块不是执行其他python脚本的最好方法,execfile语法:
execfile(filename, globals=globals(), locals=locals())
globals 和 locals 都是可选的,如果不提供参数值的话,默认为执行环境的名字空间。如果只给定 globals,那么 locals 默认和 globals 相同。如果提供 locals
f = open(filename, 'r')
exec f
f.close()
execfile(filename)
3)将模块作为脚本执行
$ python /usr/local/lib/python2x/CGIHTTPServer.py
python -c 命令行开关:
$ python -c "import CGIHTTPServer; CGIHTTPServer.test()"
$ python -m CGIHTTPServer
14.5、执行其他非Python程序
执行外部程序的 os
system(cmd) 执行程序 cmd(字符串),等待程序结束,返回退出代码
fork() 创建一个和父进程并行的子进程[通常来说和 exec*()一起使用]; 返回两次....一次给父进程一次给子进程
execl(file, arg0,arg1,...) 用参数列表 arg0, arg1
execv(file, arglist) 除了使用参数向量列表,其他的和 execl()相同
execle(file, arg0,arg1,... env) 和 execl 相同,但提供了环境变量字典 env
execve(file,arglist, env) 除了带有参数向量列表,其他的和 execle()相同
execlp(cmd, arg0,arg1,...) 于 execl()相同,但是在用户的搜索路径下搜索完全的文件路径名
execvp(cmd, arglist) 除了带有参数向量列表,与 execlp()相同
execlpe(cmd, arg0, arg1,... env) 和 execlp 相同,但提供了环境变量字典 env
execvpe(cmd,arglist, env) 和 execvp 相同,但提供了环境变量字典 env
spawn*(mode, file, args[, env]) spawn*()家族在一个新的进程中执行路径,args
参数,也许还有环境变量的字典 env;模式(mode)是个显示不同操作模式的魔术。
wait() 等待子进程完成[通常和 fock 和 exec*()一起使用]
waitpid(pid,options) 等待指定的子进程完成[通常和fock和exec*()一起使用]
popen(cmd, mode='r',buffering=-1) 执行字符串 cmd,返回一个类文件对象作为运行程序通信句柄,默认为读取模式和默认系统缓冲
python2.4 或者更新版本有 subprocess
os.system():接收字符串形式的系统命令并执行它。当执行命令的时候,python 的运行是挂起的。当我们的执行完成之后,将会以 system()的返回值形式给出退出状态,python
>>> import os
>>> result=os.system('dir')
python
>>>
>>>
>>> import os
>>> result=os.system('df -h')
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
16G 4.6G 11G 31% /
/dev/sda1 99M 13M 82M 13% /boot
tmpfs 246M 0 246M 0% /dev/shm
>>> result=os.system('free')
total used free shared buffers cached
Mem: 502680 68784 433896 0 13296 36496
-/+ buffers/cache: 18992 483688
Swap: 3670008 0 3670008
>>> result=os.system('uptime')
23:54:04 up 5:45, 3 users, load average: 0.00, 0.00, 0.00
os.open():是文件对象和 system()函数的结合。它工作方式和 system()相同,但它可以建立
一个指向那个程序的单向连接,然后如访问文件一样访问这个程序。popen()返回一个类文件对象。
>>> import os
>>> f=os.popen('uname -a')
>>> data=f.readline()
>>> f.close() #当使用完毕以后,应当 close()连接。
>>> print data,
Linux localhost.localdomain 2.6.18-238.el5 #1 SMP Thu Jan 13 16:24:47 EST 2011 i686 i686 i386 GNU/Linux
os.fork(), os.exec*(),os.wait*(), os.spawn*():略
subprocess
替换os.system():
>>> from subprocess import call
>>> import os
>>> res=call(('cat','/etc/motd'))
welcome to python world!
>>> res
0
取代os.popen():
>>> from subprocess import Popen, PIPE
>>> f = Popen(('uname', '-a'), stdout=PIPE).stdout
>>> data = f.readline()
>>> f.close()
>>> print data,
Linux localhost.localdomain 2.6.18-238.el5 #1 SMP Thu Jan 13 16:24:47 EST 2011 i686 i686 i386 GNU/Linux
>>> f = Popen('who', stdout=PIPE).stdout
>>> data = [ eachLine.strip() for eachLine in f ]
>>> f.close()
>>> for eachLine in data:
... print eachLine
...
root pts/0 2012-10-20 18:10 (192.168.128.1)
root pts/1 2012-10-20 20:30 (192.168.128.1)
root pts/2 2012-10-20 23:07 (192.168.128.1)
相关函数:
os/popen2.popen2():执行文件,打开文件,从新创建的运行程序读取(stdout),或者向
该程序写(stdin)
os/popen2.popen3():执行文件, 打开文件, 从新创建的运行程序读取(stdout和stder)
或者向该程序写(stdin)
os/popen2.popen4():执行文件,打开文件,从新创建的运行程序读取(结合 stdout,
stdout),或者向该程序写(stdin)
commands.getoutput():在子进程中执行文件,以字符串返回所有的输出
subprocess.call():创建 subprocess 的便捷函数。 Popen
态代码;与 os.system()类似,但是是较灵活的替代方案
14.6、受限执行(略)
14.7、结束执行
当程序运行完成,所有模块最高级的语句执行完毕后退出,我们便称这是干净的执行。可能有很多情况,需要从 python
处理错误方法之一是通过异常和异常处理。另外一个方法便是建造一个 “清扫器” 方法, 这样便可以把代码的主要部分放在 if语句里, 在没有错误的情况下执行,因而可以让错误的情况“正常地“终结。然而,有时也需要在退出调用程序的时候,返回错误代码以表明发生何种事件。
sys.exit() and SystemExit:
立即退出程序并返回调用程序的主要方式是 sys 模块中的 exit()函数。sys.exit()的语法为:
sys.exit(status=0)
当调用 sys.exit()时,就会引发 systemExit()异常。除非在一个 try-except 子句中,异常通常是不会被捕捉到或处理的,解释器会用给定的状态参数退出,如果没有给出的话, 该参数默认为 0。 System Exit 是唯一不看作错误的异常。仅表示要退出python。
[root@localhost python]# more args.py
#!/usr/bin/env python
import sys
def usage():
print 'At least 2 arguments (incl. cmd name).'
print 'usage: args.py arg1 arg2 [arg3... ]'
sys.exit(1)
argc = len(sys.argv)
if argc < 3:
usage()
print "number of args entered:", argc
print "args (incl. cmd name) were:", sys.argv
[root@localhost python]# ./args.py
At least 2 arguments (incl. cmd name).
usage: args.py arg1 arg2 [arg3... ]
[root@localhost python]# ./args.py xxx
At least 2 arguments (incl. cmd name).
usage: args.py arg1 arg2 [arg3... ]
[root@localhost python]# ./args.py 123 abc
number of args entered: 3
args (incl. cmd name) were: ['./args.py', '123', 'abc']
[root@localhost python]#
[root@localhost python]# ./args.py -x -2 foo
number of args entered: 4
args (incl. cmd name) were: ['./args.py', '-x', '-2', 'foo']
sys.exitfunc():默认是不可用的,但你可以改写它以提供额外的功能。当调用了 sys.exit()并
在解释器退出之前,就会用到这个函数了,这个函数不带任何参数。
os._exit() 函数,语法:os._exit(status)
功能与 sys.exit()和 sys.exitfunc()相反,根本不执行任何清理便立即退出python。与 sys.exit()不同,状态参数是必需的。通过 sys.exit()退出是退出解释器的首选方法。
os.kill():os 模块的 kill()函数模拟传统的 unix 函数来发送信号给进程。kill()参数是进程标识数(PID)和你想要发送到进程的信号。发送的典型信号为 SIGINT, SIGQUIT,或更彻底地,SIGKILL,来使进程终结。
14.8、操作系统接口
各种os模块属性(省略windows):
uname()
getuid()/setuid(uid) 获取/设置现在进程的真正的用户 ID
getgid()/setgid(gid) 获取/设置现在进程的群组 ID
getsid()/setsid() 获取会话 ID(SID)或创建和返回新的 SID。
geteuid()/setegid() 获取/设置当前进程的有效用户 ID(GID)
getegid()/setegid() 获取/设置当前进程的有效组 ID(GID)
getpgid(pid)/ setpgid(pid, pgrp) 获取和设置进程 GID 进程 PID;对于 get,如果 pid 为 0,便返回现在进程的进程 GID
getlogin()
strerror(code)
getloadavg() 返回代表在过去 1,5,15
14.9、执行环境相关模块
atexit 注册当 python
popen2 提供额外的在os.popen之上的功能: (提供通过标准文件和其他的进程交的能力;对于 python2.4 和更新的版本,使用 subpross)
commands 提供额外的在 os.system 之上的功能:把所有的程序输出保存在返回的字符串中(与输出到屏幕的相反) ;对于python2.4 和更新的版本,使用 subpross
getopt
site 处理 site-specific
platform 底层平台和架构的属性
subprocess 管理(计划替代旧的函数和模块,比如 os.system(), os.spawn*(), os.popen*(), popen2.*, command.*)