zoukankan      html  css  js  c++  java
  • python 执行环境

    一些函数

    执行其它非python程序

    1 一些函数

    callable

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

    >>> callable(1)
    False
    >>> callable(type)
    True

    compile

    compile(string,something,'eval'/'single'/'exec')。程序员通过compile来动态的生成一个可执行的代码对象。第一个是string类型的代码,第二个不知道是什么通常为''。第三个是 'eval' or 'single' or 'exec'。 当string代表的是一个可以求值的表达式的时候,选'eval',当string是一个单行的可执行的python语句选'single',如果string是多行语句选exec。

    >>> exeObj=compile('8+40','','eval')
    >>> eval(exeObj)
    48
    >>> exeObj=compile("print 'hello world'",'','single')
    >>> exec exeObj
    hello world
    >>> exeObj=compile('''
    ... for i in range(0,3):
    ...     print i
    ... ''','','exec')
    >>> exec exeObj
    0
    1
    2

    但是,

    >>> callable(exeObj)
    False

    因为 exeObj不可以用"()"来调用。

    eval和exec

    eval(), eval可以接受一个字符串(字符串的内容必须是一个表达式)或者compile返回的可执行代码段作为参数,然后对参数求值。

    exec 与 eval一样。不过exec还可以执行文件,但文件内容必须是可执行的代码。比如:

    我们有一个文件 runFor.py 

    bash-2.05$ cat runFor.py
    for i in range(0,5):
            print i

    在python里面,我们用exec来执行这个文件

    >>> f=open('runFor.py')
    >>> exec f
    0
    1
    2
    3
    4

    所以,exec可以执行文件。但是我们再运行一下 exec f

    >>> exec f
    >>>

    什么都没有,这是为什么呢? 这是因为此时f已经读到文件末尾了,我们用f的tell属性来看当前文件内指针在哪,

    >>> f.tell()
    31L

    再对比一下文件的大小

    >>> import os
    >>> os.path.getsize('runFor.py')
    31L

    可知当前文件指针在结尾处了,我们可以用f.seek(0)来把指针移动回开头

    >>> f.seek(0)
    >>> exec f
    0
    1
    2
    3
    4

    input

    input等同于eval和raw_input的组合。 我们用例子说明:

    >>> a=raw_input('input something: ')
    input something: [1,2,3,4]
    >>> a
    '[1,2,3,4]'

    上面我们用raw_input来读取输入,虽然我们输入的是[1,2,3,4],但是实际上返回的是string

    >>> a=input('input something: ')
    input something: [1,2,3,4]
    >>> a
    [1, 2, 3, 4]

    而如果用input,我们输入的是[1,2,3,4] 返回的也是[1,2,3,4] 相当于用eval 把raw_input的值求值了一下。

    2 执行非python程序

    2.1 os.system

    os.system('cmd') 会执行cmd。cmd可以是命令也可以是外部程序,os.system在执行后会把输出打印到标准输出,同时会返回一个值,如果成功返回0,如果不成功返回非零。

    >>> import os
    >>> a=os.system('uname')
    SunOS
    >>> a
    0

    2.2 os.popen

    与os.system一样,os.popen('cmd')会执行外部命令cmd。但是os.popen会把返回值放入一个文件对象。

    >>> import os
    >>> a=os.popen('ls -l')
    >>> print a.readline()
    total 64
    
    >>> print a.readline()
    -rw-r--r--   1 oratop   dba            0 May 22 17:17 a
    
    >>> print a.readline()
    -rw-r--r--   1 oratop   dba           59 May 16 13:54 importee.py
    
    >>> print a.readline()
    -rw-r--r--   1 oratop   dba          259 May 16 13:54 importee.pyc
    
    >>> print a.readline()
    -rw-r--r--   1 oratop   dba          282 May 16 11:42 m1.pyc
    View Code

    2.3 exec*函数

    python的os模块中有许多exec开头的函数可以用来执行外部命令,它们是

    os.execl(file, arg*)
    os.execle(file, arg*, env)
    os.execlp(file, arg*)
    os.execlpe(file, arg*, env)
    os.execv(file, args)
    os.execve(file, args, env)
    os.execvp(file, args)
    os.execvpe(file, args, env)

    这些函数都会新建一个执行流来执行file这个参数代表的外部程序,unix中这个执行流会load进当前的进程中,所以在unix中你会发现pid不变,但是程序的内容已经变了。由于是新的执行流,所以这些函数不会返回。

    在这些函数执行的时候,当前的进程会被立即替换掉,但是Open file objects and descriptor这些不会flush,所以你最好在调用exec*函数前先掉用sys.stdout.flush 或者 os.fsync() 。

    比如:

    首先在一个窗口打开python

    bash-2.05$ python
    Python 2.5 (r25:51908, Sep 20 2006, 06:18:53)
    [GCC 3.4.6] on sunos5
    Type "help", "copyright", "credits" or "license" for more information.
    >>>
    >>>
    >>>
    >>>

    然后我们在另外一个窗口追踪,

    bash-2.05# ptree 26487
    390   /usr/lib/ssh/sshd
      26473 /usr/lib/ssh/sshd
        26476 /usr/lib/ssh/sshd
          26478 -sh
            26482 -bash
              26487 python
    bash-2.05# pfiles 26487
    26487:  python
      Current rlimit: 256 file descriptors
       0: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       1: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       2: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
    bash-2.05#
    View Code

    可以看到当前我们的python进程是26487 而 打开了一共3个文件。下面我们用python去打开一个文件,

    >>> f=open('/tmp/test.txt')

    然后回到监控窗口查看,

    bash-2.05# pfiles 26487
    26487:  python
      Current rlimit: 256 file descriptors
       0: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       1: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       2: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       3: S_IFREG mode:0644 dev:0,2 ino:185403968 uid:2001 gid:101 size:5
          O_RDONLY|O_LARGEFILE
    View Code

    显示打开了0,1,2,3一共4个文件。第四个文件是:

    bash-2.05# find /tmp -inum 185403968
    /tmp/test.txt

    ok,现在我们回到第一个进程用exec执行点别的,

    >>> import os
    >>> os.execlp('sleep','','999')

    然后回来监控

    bash-2.05# ptree 26487
    390   /usr/lib/ssh/sshd
      26473 /usr/lib/ssh/sshd
        26476 /usr/lib/ssh/sshd
          26478 -sh
            26482 -bash
              26487  999
    bash-2.05# pfiles 26487
    26487:   999
      Current rlimit: 256 file descriptors
       0: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       1: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       2: S_IFCHR mode:0620 dev:32,0 ino:3982 uid:0 gid:7 rdev:24,2
          O_RDWR|O_NOCTTY|O_LARGEFILE
       3: S_IFREG mode:0644 dev:0,2 ino:185403968 uid:2001 gid:101 size:5
          O_RDONLY|O_LARGEFILE
    View Code

    我们发现当前进程的pid仍然是26487,但是已经不是python进程了。而是我们执行的sleep 999进程,同时发现,虽然进程已经被替换了,但是open file里面仍然有 ino:185403968这个文件。

    关于函数名字后面的l,v,e,p 他们都有各自的含义。

    l与v对应,l表示参数都是放在arg*这样的参数列表里, 而v表示 参数放在一个list或者tuple中传递进来。如:

    >>> import os
    >>> os.execl('/usr/bin/ls','','-l','importee.pyc')
    -rw-r--r--   1 oratop   dba          259 May 16 13:54 importee.pyc
    
    
    >>> import os
    >>> atuple=('','-l','importee.pyc')
    >>> os.execv('/usr/bin/ls',atuple)
    -rw-r--r--   1 oratop   dba          259 May 16 13:54 importee.pyc
    View Code

    l中,参数是一个一个传递的,而v中参数放入一个tuple传递。要注意的是,不管怎么传递,似乎参数列表的第一个参数都应该为空,否则会被忽略。

    p的含义是path,如果不加p,向上面的例子中,你就要输入/usr/bin/ls这样python才能找到ls,而用execlp的话就可以写成execlp('ls','','arg1','arg2',......)因为这里的p代表函数会寻求当前PATH环境变量里面的搜索路径。

    e是环境变量的意思。 不以e结尾的这几个函数,在替换后的进程里会继续使用之前进程的env变量。但是如果使用了带e结尾的函数,则新进程的环境变量由函数指定,我们试一下:

    以 execlpe(file,arg*,env)为例 在一个窗口中打开python,并设置mapObj如下。这个mapObj将传给env参数,注意的是这个字典必须是key value都位字符串的字典。

    >>> import os
    >>> mapObj={'ENV':'200'}
    View Code

    监控窗口中看到这个进程的环境变量如下,看进程的环境变量用 pargs

    bash-2.05# pargs -e 26893
    26893:  python
    envp[0]: PWD=/export/home/oratop
    envp[1]: TZ=PRC
    envp[2]: ORACLE_SID=topdev
    envp[3]: HZ=
    envp[4]: HOSTNAME=apc_dev1db1
    envp[5]: LD_LIBRARY_PATH=/opt/oratop/product/10.2.0/top_db/lib:
    envp[6]: MACHTYPE=sparc-sun-solaris2.9
    envp[7]: ORACLE_BASE=/opt/oratop
    envp[8]: DERBY_INSTALL=/opt/derby/db-derby-10.1.2.1-bin
    envp[9]: ORACLE_HOME=/opt/oratop/product/10.2.0/top_db
    envp[10]: LOGNAME=oratop
    envp[11]: SHLVL=1
    envp[12]: SHELL=/bin/bash
    envp[13]: TNS_ADMINDMIN=/opt/oratop/product/10.2.0/top_db/network/admin
    envp[14]: HOSTTYPE=sparc
    envp[15]: OSTYPE=solaris2.9
    envp[16]: HOME=/export/home/oratop
    envp[17]: TERM=vt100
    envp[18]: PATH=/opt/oratop/product/10.2.0/top_db/bin:/opt/oratop/product/10.2.0/top_db/bin:/usr/local/bin:/opt/sybase/dba/bin:/opt/sybase/bin:/opt/sybase/install:/opt/sybase/ASE-12_5/bin:/opt/sybase/ASE-12_5/install:/opt/sybase/OCS-12_5/bin:/usr/bin:/bin:/usr/bin:/usr/ucb:/etc:.
    envp[19]: DERBY_HOME=/opt/derby/db-derby-10.5.3.0-bin
    envp[20]: _=/usr/local/bin/python
    bash-2.05#
    bash-2.05#
    View Code

    我们在原窗口执行execlpe

    >>> os.execlpe('sleep','','999',mapObj)

    新窗口查看

    bash-2.05# pargs -e 26893
    26893:   999
    envp[0]: ENV=200

    可见环境变量已经被替换。

    2.4 spawn*函数

    spawn*和 exec*一样,但是参数列表略有不同。spawn*(mode,file,args,env)。可以看到只是多了一个mode。spawn和exec的区别是,exec是取代当前进程执行,而spawn是创建新进程执行,类似于把fork和exec一起用。

  • 相关阅读:
    【转】70个经典的 Shell 脚本面试问题
    【转】最牛B的编码套路
    【转】Flex 布局语法教程
    【转】程序员7大软技能测验 你得几分?
    【转】为什么事务日志自动增长会降低你的性能
    【hive】——metastore的三种模式
    【hive】——Hive基本操作
    【hive】——Hive初始了解
    【hive】——Hive四种数据导入方式
    【hive】——Hive sql语法详解
  • 原文地址:https://www.cnblogs.com/kramer/p/3745985.html
Copyright © 2011-2022 走看看