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.*)