绝对精华,Python学习笔记之Python执行环境

目录 Python

1、可调用对象

许多Python对象都是可调用的,即任何能通过函数操作符“()”来调用的对象。Python有4种可调用对象:函数方法以及一些类实例,这些对象的任何引用或者别名都是可调用的。

(1)函数(3种函数)

①内建函数(BIF,built-in function)

由C/C++写的,编译过后放入Python解释器,然后把它们作为第一(内建)名称空间的一部分加载进系统。这些函数在_builtin_模块里,并作为_builtins_模块导入到解释器中。

内建函数的属性包括:

  • bif.__doc__ 文档字符串(或None)
  • bif.__name__ 字符串类型的函数名字
  • bif.__self__ 设置为None(保留给内建方法)
  • bif.__module__ 存放bif定义的模块名字(或None)

②用户定义的函数(UDF,user-defined function)

用Python书写,定义在模块的最高级,作为全局名称空间的一部分装载进系统。函数也可以在其他的函数体内定义。

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 包含了自由变量的引用的单元对象元组

③lambda表达式

用lambda关键字创建,不使用def语句创建。

用lambda关键字创建的函数对象没有命名,需要将其引用赋值给一个变量才可以被调用。

用lambda关键字创建的函数对象和用户自定义函数具有相同的属性。

(2)方法

①内建方法(BIM)

只有内建类型(BIT)才有内建方法。BIM和BIF调用type()具有相同的结果builtin_function_or_method。BIM和BIF两者都具有相同属性。不同之处在于BIM的__self__属性指向一个Python对象,而BIF指向None。

对于类和实例都可以以该对象为参数调用内建函数dir()来获得它们的数据和方法属性。

②用户定义的方法(UDM)

包含在类定义之中,仅有定义它们的类可以使用。

UDM与类对象是关联的(非绑定方法),但是只能通过类的实例来调用(绑定方法)。

无论UDM是否绑定,所有的UDM都是相同的类型–“实例方法”。

UDM包含的常用属性有:

  • udm.__doc__ 文档字符串(与udm.im_func.__doc__相同)
  • udm.__name__ 字符串类型的方法名字(与udm.im_func.__name__相同)
  • udm.__module__ 定义udm的模块的名字(或None)
  • udm.im_class 方法相关联的类(对于绑定的方法;如果是非绑定,那么为要求udm的类)
  • udm.im_func 方法的函数对象
  • udm.im_self 如果绑定的话为相关联的实例,如果非绑定为None

(3)类

“调用”类的结果便是创建了类实例。程序员可以通过实现__init__()方法来自定义实例化过程。调用类时,传入的参数都会交给__init__()方法。

(4)类的实例

Python给类提供了特殊方法__call__(),允许程序员创建可调用的对象(实例)。

默认情况下,该方法没有实现,所以大多数实例是不可调用的。在类定义中覆盖该方法,类的实例就成为可调用对象了。

class C(object):

def __call__(self,*args):

….

>>>c=C()

>>>c() #调用实例12345

调用这样的实例对象等同于调用__call__()方法。任何实例调用中给出的参数都会传入到__call__()方法中。

c()与c.__call__(c)的效果相同,c(arg)与c.__call__(c,arg)一样,这里c也作为参数出现,是因为实例将作为每次方法调用的第一个参数。

2、代码对象

可调用物代码对象构成。

代码对象包括语句赋值表达式其他可调用物组成。

代码对象可以作为函数或者方法调用的一部分来执行,也可用exec语句或内建函数eval()来执行。代码对象转换成字节码,然后包含执行环境(可调用物),便可以执行了。

3、可执行的对象声明和内建函数

(1)callable()

布尔函数,确定一个对象是否可以通过函数操作符(())来调用。

(2)compile()

允许在运行时刻迅速生成代码对象,然后调用exec语句或内建函数eval()来执行它们。exec语句和eval()内建函数都可以执行字符串形式的代码。compile()函数提供一次性字节代码预编译。

compile(string,file,type)1

string表示要编译的Python代码,必须。

file表示存放代码对象的文件的名字(字符串类型),虽然必须,但是通常被置为空。

type表示代码对象的类型,有三个可能值:

  • eval’:可求值的表达式(与eval()一起使用)
  • ‘single’:单一可执行语句(与exec一起使用)
  • ‘exec’:可执行语句组(与exec一起使用)

(3)eval()

对表达式求值,可以是字符串或内建函数compile()创建的预编译代码对象。

eval(obj,globals=globals(),locals=locals())1

obj 是字符串或是已编译为代码对象的表达式,globals必须是字典,locals可以是任意的映射对象。

(4)exec语句

exec语句执行代码对象或字符串形式的Python代码。exec语句还可以接受有效的Python文件对象。一旦执行完毕,继续对exec的调用就会失败,因为第一次执行时,exec已经从文件中读取了全部的数据且停留在文件的末尾,可以使用file对象的tell()方法来告诉我们处于文件的何处,同时使用os.path.getsiae()来告诉我们文件的大小,就可以确认是否到达了文件的末尾。可以调用file对象的seek()方法到文件的开头再次调用exec。

exec obj1

(5)input()

它是eval()和raw_input()的组合,等价于eval(raw_input())。将用户输入作为Python表达式进行求值。input()方法返回一个Python对象。

4、执行其他(Python)程序

(1)导入

第一次导入模块会执行模块最高级的代码。

Python解释器通过检测__name__来确定是否要调用脚本,比如”if __name__==’__main__’”,若相等的话,脚本会执行main内代码,否则只是打算导入这个脚本。

(2)execfile()

execfile(filename,globals=globals(),locals=locals())1

语法类似于eval()函数,globals和locals都是可选的,如果不提供globals和locals,默认为执行环境的名称空间;如果只提供globals,locals默认和globals相同。

方法1:

f=open(filename,’r’)exec f

f.close()123

<=>

方法2:

execfile(filename)1

方法1仅可以在现有的执行环境下运行,方法2可以在指定的全局和局部的名称空间执行。

(3)将模块作为脚本执行(2.4)

①从shell或DOS提示符直接把模块作为脚本来执行

$ myScript.py #从工作目录调用脚本1

or

$ python myScript.py 1

②如果模块是标准库的一部分,安装在site-packages里,或者仅仅是包里面的模块,需要提供完整路径或借助于Python的导入机制来工作。

$ python -c “import CGIHTTPServer;CGIHTTPServer.test()” #让Python导入机制工作1

or

$ python /usr/local/lib/python2x/CGIHTTPServer.py #完整路径名1

or

$ python -m CGIHTTPServer #能在类库中执行作为脚本的模块而不是作为导入1

5、执行其他(非Python)程序

其他的非Python程序包括:二进制可执行文件其他的shell脚本等。

执行其他的非Python程序需要满足的条件:一个有效的执行环境,如允许文件访问和执行,脚本文件必须能访问它们的解释器,二进制必须是可访问的。

(1)os.system()

接受字符串形式的系统命令并执行它。

执行命令时,Python运行被挂起,命令执行完,将以system()的返回值形式给出退出状态,Python继续执行。

system()通常和不会产生输出的命令一起使用,如压缩或转换文件的程序,挂载磁盘到系统的程序,返回值0表示成功,非0表示其他类型的错误。

(2)os.popen()

popen()函数是文件对象和system()函数的结合。

>>>f=os.popen(‘uname -a’)

>>>data=f.readline()>>>f.close()

>>>print data1234

popen()的工作方式和system()相同,但可以通过指向程序的单向连接,像访问文件一样访问程序。popen()返回一个类文件对象。

(3)os.fork(),os.exec*(),os.wait*()

os.fork()创建一个和父进程并行的子进程(通常来说和exec*()一起使用);返回两次…一次给父进程一次给子进程

os.exec*()函数装载文件或者命令,并用参数列表来执行它。

(4)os.spawn*()

(5)subprocess模块

**6、结束执行

(1)sys.exit()和SystemExit异常**

sys.exit()立即退出程序并返回调用程序。当调用sys.exit()时,就会引发SystemExit异常。SystemExit异常是唯一不看作错误的异常,仅仅表示要退出Python的愿望。sys.exit()经常用在命令调用的中途发现错误之后。

(2)sys.exitfunc()

当调用了exit()函数并在解释器退出之前,就会用到这个函数,该函数默认是不可用的,你可以改写它以提供额外的功能。

(3)os._exit()函数

os._exit()函数与sys.exit()和sys.exitfunc()相反,根本不执行任何清理便立即退出Python。

os._exit(status) 状态参数status是必需的。通过sys.exit()退出是解释器的首选方法。

(4)os.kill()函数

kill()函数模拟传统的unix函数发送信号给进程,参数为进程标识符(PID)和信号,信号常见的有SIGINT,SIGQUIT,SIGKILL等。

7、各种操作系统接口

除非标明适用于Windows环境,否则只适用于POSIX系统。

  • uname() 获得系统信息(主机名、操作系统版本、补丁级别、系统结构等)
  • getuid()/setuid(uid) 获取/设置现在进程的真正的用户ID
  • getpid()/getppid() 获取真正的现在/父进程ID(PID)(Win32)
  • getgid()/setgid(gid) 获取/设置现在进程的群组ID
  • getsid()/setsid() 获取会话ID(SID)或创建和返回新的SID
  • umask(mask) 设置现在的数字umask,同时返回先前的那个(mask用于文件许可)(Win32)
  • getenv(ev)/putenv(ev,value),environ获取和设置环境变量ev的值;
  • os.environ属性是描述当前所有环境变量的字典(Win32)
  • geteuid()/seteuid() 获取/设置当前进程的有效用户ID(UID)
  • getegid()/setegid() 获取/设置当前进程的有效组ID(GID)
  • getpgid(pid)/setpgid(pid,pgrp) 获取/设置PID进程的GID;对于get,如果pid为0,便返回现在进程的GID
  • getlogin() 返回运行现在进程的用户登录
  • times() 返回各种进程时期的元组(Win32)
  • strerror(code) 返回和错误代码对应的错误信息(Win32)
  • getloadavg()(2.3) 返回代表在过去1,5,15分钟内的系统平均负载值的元组

8、相关模块

  • atexit(2.0) 注册当Python解释器退出时的执行句柄
  • popen2 提供额外的在os.popen之上的功能;提供通过标准文件和其他的进程交互的能力
  • commands 提供额外的在os.sysytem之上的功能;把所有的程序输出保存在返回的字符串中(与输出到屏幕的相反)
  • getopt 在这样的应用程序中的处理选项和命令行参数
  • site 处理site-specific模块或包
  • platform(2.3) 底层平台和架构的属性
  • subprocess(2.4)管理(计划替代旧的函数和模块,比如os.system()、os.spawn*()、os.popen*()、popen2.和commands.)

每天1篇必读运维大牛亲笔绝密干货贴,收藏前必须关注大数据架构师专家微信公众号 xinsz08 ,联系微信czq100w,加入各城市运维安全总群,与行业大牛同台交流学习。