执行环境

Python 核心编程[第十四章]

0x00可调用对象

  许多 Python 对象都是可调用的,任何能通过函数操作符 “()” 来调用的对象。要调用可调用对象,函数操作符得紧跟在可调用对象之后。 Python 中有四种可调用对象:函数、方法、类、以及一些类的实例。这些对象的任何引用或者别名都是可调用的。

一、函数

  Python 有三种不同类型函数对象。内建函数,用户定义函数,lambda表达式。

1.内建函数

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

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

  可以使用 dir() 列出函数的所有属性,从内部机制来看,并且 BIF 和 BIM(内建方法) 属于相同的类型.

2.用户定义函数

  用户定义的函数通常是用 Python 写的,定义在模块的最高级,因此会作为全局名称空间的一部分装载到系统中。

用户自定义函数属性描述
udf.__doc__文档字符串
udf.__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包含了自由变量的引用的单元对象元组

二、方法

1.内建方法

  内建方法与内建函数类似,只有内建类型有内建方法。内建函数和内建方法也享有相同属性。不同之处在于内建方法的 __self__属性指向一个 Python 对象,而内建方法指向 None。对于类和实例,都能以该对象为参数,通过内建函数 dir() 来获取他们的数据和方法属性,这也可以用在内建方法上。

内建方法的属性描述
bim.__doc__文档字符串
bim.__name__字符串类型的函数名字
bim.__self__绑定对象
2.用户定义方法

  用户定义的方法包含在类定义之中,,只是拥有标准函数的包装,仅有定义它们的类可以使用。在没有被字类定义覆盖掉的情况下,也可以通过字类实例调用它们。用户定义的方法是与类对象相关联的,但是只能通过类的实例来调用。

属性描述
udm.__doc__文档字符串
udm.__name__字符串类型的类的名字方法
udm.__module__定义 udm 的模块的名字
udm.im_class方法相关联的类
udm.im_func方法的函数对象
udm.im_self如果绑定的话为相关联的实例,如果非绑定为 None

三、类

  我们可以利用类的可调用性来创建实例。“调用”类的结果便是创建了实例,即实例化。类有默认构造器,该函数什么都不做,基本上只有一个 pass 语句。程序员可以通过实现 __init__方法,来自定义实例化过程。实例化调用的任何参数都会传到构造器里。

四、类的实例

  Python 给类提供了名为 __call__ 的特别方法,该方法允许程序员创建可调用的对象。默认情况下 __call__ 方法是没有实现的,这意味着大多数实例都是不可调用的。然而,如果类定义中覆盖了这个方法,那么这个类的实例就成为可调用的了。调用这样的实例对象等同于调用 __call__ 方法。自然地,任何在实例调用中给出的参数都会被传入到 __call__ 中。那么 foo() 就和 foo.__call__(foo) 的效果相同,这里 foo 也作为参数出现,因为是对自己的引用,实例将自动为每次方法调用的第一个参数。如果 __call__() 有参数,比如 (self,arg),那么 foo(arg) 就和调用 foo.__call__(foo,arg)一样。

 class C(object):
 	def __call__(self,*args):
 		print("Hello",args)
 # 实例化
 c = C()
 # 调用实例
 c()

0x01代码对象

  Python 语句、赋值、表达式、模块等,这些可执行对象无法像可调用物那样被调用。每个可调用物的核心都是代码对象,由语句、赋值、表达式和其他可调用物组成。可调用物又可以递归分解到下一层,那有自己的代码对象。
  代码对象可以作为函数或方法调用的一部分来执行,也可以用 exec 语句或内建函数 eval() 来执行。如果要执行 Pyhton 代码,那么该代码必须要先转换成字节码。这才是真正的代码对象。不过,它们不包含任何关于他们执行环境的信息,这边是可调用物存在的原因,它被用来包装一个代码对象并提供额外的信息。
  udf.func_code 属性所表示的就是代码对象。因为 udm.im_func 也是一个函数对象,所以他同样有自己的 udm.im_func.func_code 代码对象。所以,函数对象仅是代码对象的包装,方法则是给函数对象的包装。

0x02可执行的对象声明和内建函数

可执行的内建函数和语句描述
callable(obj)如果 obj 可调用,返回 True ,否则返回 False
compile(string,file,type)从 type 类型中 创建代码对象;file 是代码存放的地方 (通常设置为"")
eval(obj,globals=globals(),locals=locals()对 obj 进行求值,obj 是已编译为代码对象的表达式,或是一个字符串表达式;可以给出全局/局部的名称空间
exec obj执行 obj、单一的 Python 语句或者语句的集合,也就是说格式是代码对象或者字符串;obj 也可以是一个文件对象
input(prompt="")等同于 eval(raw_input(prompt=""))

一、callable()

  它是一个布尔函数,确定一个对象是否可以通过函数操作符 “()” 来调用。如果可以便返回 True 否则返回 False。

二、compile()

  compile()函数允许程序员在运行时刻迅速生成代码对象,然后就可以用 exec 语句或内建函数 eval() 来执行这些对象或者对他们进行求值。一个很重要的观点是:exec 和 eval() 都可以执行字符串格式的 Python 代码。当执行字符串形式的代码时,每次都必须对这些代码进行字节编译处理。compile() 函数提供了一次性字节代码预编译,以后每次调用的时候都不用编译了。
  compile 的三个参数都是必须的,第一个参数代表了要编译的 Python 代码。第二个字符串代表了存放代码对象的文件的名字。最后的参数是一个字符串,它用来表明代码对象的类型。有三个可能值:‘eval’ 可求值的表达式[和 eval() 一起使用] ‘single’ 单一可执行语句[和 exec 一起使用] ‘exec’ 可执行语句组 [和 exec 一起使用]

1.可求值表达式
  code = compile('100 + 200'.'','eval')
  eval(code)
2.单一可执行语句
  code = compile('print('Hello'),'','single'')
  exec code

3可执行语句组
  code = compile("""a = 'Hello
  print(a)
 '""",'',''exec)
  exec code

三、eval()

  对表达式求值,第一个参数可以是字符串或者 complie() 创建的预编译代码对象。第二个和第三个参数都是可选,分别代表了全局和局部名称空间中的对象。globals 必须是一个字典,local 可以是任意的映射对象。

  eval('520 + 1')

四、exec

和 eval() 相似,exec 语句执行代码对象或字符串形式的 Python 代码。

  # exec 还可以接收有效的 Python 文件对象。
  # xxx.py
  print('Hello')
 
  # a.py
  f = open('xxx.py','r')
  exec f
  # 注意:一旦调用过一次之后,继续调用将会失效。
  # 即,不再运行 xxx.py 中的代码,因为这个时候 exec 已从文件中读取了全部的数据且停留在文件的末尾。

0x03执行

一、执行其他 Python 程序

1.导入

  第一次导入模块会执行模块最高级的代码(没有缩进的代码),只有属于模块最高级的代码才是全局变量,全局类和全局函数的声明。不过可以把每次导入不过并不想执行的代码放进 if __name__ == '__main__'的内部。

2.execfile()

执行一个文件中的代码

  #语法
  # execfile(filename,globals = globals(), locals = locals())
  # 其中的用法与 eval 类似
  f = open('xxx.py','r')
  exec f
  f.close()
  <=> 
  execfile(filename)
3.将模块作为脚本执行

  在命令行中执行,python -m 选项 和 -c 选项。当用 -c 导入某个模块时,该模块下 if __name__ == ‘__main__’ 中的代码不会被自动执行(此时导入的模块只是当作一个模块被执行)。所以可以用 -m 选项把某个模块作为一个脚本文件执行(此时该模块被当作一个脚本执行,相对 ‘__main__’ 便可以自己执行)。

二、执行其他非 Python 程序

  其他程序包括二进制可执行文件或其他脚本语言的源代码。要有可执行环境:允许文件访问和执行,脚本文件必须能访问它们的解释器(perl\bash),二进制文件必须可访问。

xxx

1. os.system()

  接收字符串形式的系统命令,并执行它。当执行命令的时候,Python 的运行是挂起的。当我们的执行完成之后,会以 system() 的返回值形式给出退出状态, Python 的执行也会继续。
system() 保留了现有的便准文件,包括标准的输出,意味着执行任何命令和程序显示输出都会传达到标准输出上。
  system() 通常和不会产生输出的命令一起使用,其中的一些命令包括了压缩和转化文件的程序,挂载磁盘到系统的程序,或其他执行特定任务的命令-----通过退出状态显示成功或失败而不是通过输入/输出通信。通常的约定是利用退出状态,0 表示成功,非 0 表示其他类型的错误。

2. os.popen

  popen() 函数是文件对象和 system() 函数的结合。他工作方式和 system() 相同,但它可以建立一个指向那个个程序的单项连接,然后像访问文件一样访问这个程序。如果程序要求输入,那么你要用 ‘w’ 模式写入那个命令来调用 popen()。‘r’ 模式允许 spawn 命令,那么当它写入标准输出的时候,你就可以通过类文件句柄使用熟悉的 file 对象的 read() 方法来读取输入。就像对于文件,当你使用完毕,你应该 close() 连接。

3. os.fork()、os.exec()、os.wait()
4. os.spawn*()

三、结束执行

1. sys.exit() and SystemExit

  立刻退出程序并返回调用程序。当调用 sys.exit() 时,就会引发 systemExit() 异常。该异常通常是不会被捕捉到或处理的,解释器会用给定的状态参数退出,如果没有给出的话,该参数默认为 0 .System Exit 是唯一不看做错误的异常。通过 sys.exit() 退出是退出解释器的首选方法。

2.sysexitfunc()

  该函数默认是不可用的,但是你可以改写它以提供额外的功能。当调用了 sys.exit() 并在解释器退出之前,就会用到这个函数了。这个函数不带任何参数的,所以你创建的函数也应该是无参的。
如果 sys.exitfunc 已经被先前定义的 exit 函数覆盖了,最好的方法是把这段代码作为 exit() 函数的一部分来执行。一般来说,exit 函数用于执行某些类型的关闭活动,比如关闭文件和网络连接,最好用于完成维护任务,比如解释先前保留的系统资源。

3. os._exit() 函数

  os 模块的 _exit() 函数不应该在一般应用中使用(只适用于特定平台 Unix Win32 等)。这个函数提供的功能与 sys.exit() 和 sys.exitfunc() 相反,根本不执行任何清理便立刻退出 Python 程序。与 sys.exit() 不同,状态参数是必须的。

  os._exit(status)
4. os.kill() Function

  os 模块的 kill() 函数模拟传统的 unix 函数来发送信号给进程。kill() 参数是进程表示数(PID)和你想要发送进程的信号。发送的典型信号为 SIGINT、SIGQUIT 或 SIGKILL,来使进程终结。

0x04操作系统相关的各种接口

xxx

0x05相关模块

xxx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值