`
booby325
  • 浏览: 383353 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

python核心编程学习笔记-执行环境

阅读更多

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

0

1

2

3

4

5

 

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

>>> 

 

2execfile():导入模块不是执行其他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)         等待指定的子进程完成[通常和fockexec*()一起使用]

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():执行文件, 打开文件, 从新创建的运行程序读取(stdoutstder) 

或者向该程序写(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() 获取/设置当前进程的有效用户 IDGID

getegid()/setegid() 获取/设置当前进程的有效组 IDGID

getpgid(pid)/ setpgid(pid, pgrp)     获取和设置进程 GID 进程 PID;对于 get,如果 pid  0,便返回现在进程的进程 GID

getlogin()          返回运行现在进程的用户登录

strerror(code)       返回和错误代码对应的错误信息

getloadavg()        返回代表在过去 1515 分钟内的系统平均负载值的元组。

 

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics