• python标准库介绍——1 os详解


    == os 模块 ==
    
    ``os`` 模块为许多操作系统函数提供了统一的接口.
    
    这个模块中的大部分函数通过对应平台相关模块实现, 比如 ``posix`` 和 
    ``nt. os`` 模块会在第一次导入的时候自动加载合适的执行模块. 
    
    === 处理文件===
    
    内建的 ``open / file`` 函数用于创建, 打开和编辑文件, 如 [Example 1-27 #eg-1-27] 所示. 而 
    ``os`` 模块提供了重命名和删除文件所需的函数. 
    
    ====Example 1-27. 使用 os 模块重命名和删除文件====[eg-1-27]
    
    ```
    File: os-example-3.py
    
    import os
    import string
    
    def replace(file, search_for, replace_with):
        # replace strings in a text file
    
        back = os.path.splitext(file)[0] + ".bak"
        temp = os.path.splitext(file)[0] + ".tmp"
    
        try:
            # remove old temp file, if any
            os.remove(temp)
        except os.error:
            pass
    
        fi = open(file)
        fo = open(temp, "w")
    
        for s in fi.readlines():
            fo.write(string.replace(s, search_for, replace_with))
    
        fi.close()
        fo.close()
    
        try:
            # remove old backup file, if any
            os.remove(back)
        except os.error:
            pass
    
        # rename original to backup...
        os.rename(file, back)
    
        # ...and temporary to original
        os.rename(temp, file)
    
    #
    # try it out!
    
    file = "samples/sample.txt"
    
    replace(file, "hello", "tjena")
    replace(file, "tjena", "hello")
    ```
    
    === 处理目录===
    
    ``os`` 模块也包含了一些用于目录处理的函数. 
    
    ``listdir`` 函数返回给定目录中所有文件名(包括目录名)组成的列表, 如 
    [Example 1-28 #eg-1-28] 所示. 而 Unix 和 Windows 中使用的当前目录和父目录标记(. 和 .. )不包含在此列表中. 
    
    ====Example 1-28. 使用 os 列出目录下的文件====[eg-1-28]
    
    ```
    File: os-example-5.py
    
    import os
    
    for file in os.listdir("samples"):
        print file
    
    *B*sample.au
    sample.jpg
    sample.wav
    ...*b*
    ```
    
    ``getcwd`` 和 ``chdir`` 函数分别用于获得和改变当前工作目录. 如 [Example 1-29 #eg-1-29] 所示. 
    
    ====Example 1-29. 使用 os 模块改变当前工作目录====[eg-1-29]
    
    ```
    File: os-example-4.py
    
    import os
    
    # where are we?
    cwd = os.getcwd()
    print "1", cwd
    
    # go down
    os.chdir("samples")
    print "2", os.getcwd()
    
    # go back up
    os.chdir(os.pardir)
    print "3", os.getcwd()
    
    *B*1 /ematter/librarybook
    2 /ematter/librarybook/samples
    3 /ematter/librarybook*b*
    ```
    
    ``makedirs`` 和 ``removedirs`` 函数用于创建或删除目录层,如 [Example 1-30 #eg-1-30] 所示. 
    
    ====Example 1-30. 使用 os 模块创建/删除多个目录级====[eg-1-30]
    
    ```
    File: os-example-6.py
    
    import os
    
    os.makedirs("test/multiple/levels")
    
    fp = open("test/multiple/levels/file", "w")
    fp.write("inspector praline")
    fp.close()
    
    # remove the file
    os.remove("test/multiple/levels/file")
    
    # and all empty directories above it
    os.removedirs("test/multiple/levels")
    ```
    
    ``removedirs`` 函数会删除所给路径中最后一个目录下所有的空目录. 
    而 ``mkdir`` 和 ``rmdir`` 函数只能处理单个目录级. 如 [Example 1-31 #eg-1-31] 所示.
    
    ====Example 1-31. 使用 os 模块创建/删除目录====[eg-1-31]
    
    ```
    File: os-example-7.py
    
    import os
    
    os.mkdir("test")
    os.rmdir("test")
    
    os.rmdir("samples") # this will fail
    
    *B*Traceback (innermost last):
      File "os-example-7", line 6, in ?
    OSError: [Errno 41] Directory not empty: 'samples'*b*
    ```
    
    如果需要删除非空目录, 你可以使用 ``shutil`` 模块中的 ``rmtree`` 函数. 
    
    === 处理文件属性===
    ``stat`` 函数可以用来获取一个存在文件的信息, 如 [Example 1-32 #eg-1-32] 
    所示. 它返回一个类元组对象(stat_result对象, 包含 10 个元素), 
    依次是st_mode (权限模式), st_ino (inode number), st_dev (device), 
    st_nlink (number of hard links), st_uid (所有者用户 ID), st_gid 
    (所有者所在组 ID ), st_size (文件大小, 字节), st_atime (最近一次访问时间), 
    st_mtime (最近修改时间), st_ctime (平台相关; Unix下的最近一次元数据/metadata修改时间, 
    或者 Windows 下的创建时间) - 以上项目也可作为属性访问. 
    
    ``` [!Feather 注: 原文为 9 元元组. 另,返回对象并非元组类型,为 struct.]
    
    ====Example 1-32. 使用 os 模块获取文件属性====[eg-1-32]
    
    ```
    File: os-example-1.py
    
    import os
    import time
    
    file = "samples/sample.jpg"
    
    def dump(st):
        mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime = st
        print "- size:", size, "bytes"
        print "- owner:", uid, gid
        print "- created:", time.ctime(ctime)
        print "- last accessed:", time.ctime(atime)
        print "- last modified:", time.ctime(mtime)
        print "- mode:", oct(mode)
        print "- inode/dev:", ino, dev
    
    #
    # get stats for a filename
    
    st = os.stat(file)
    
    print "stat", file
    dump(st)
    print
    
    #
    # get stats for an open file
    
    fp = open(file)
    
    st = os.fstat(fp.fileno())
    
    print "fstat", file
    dump(st)
    
    *B*stat samples/sample.jpg
    - size: 4762 bytes
    - owner: 0 0
    - created: Tue Sep 07 22:45:58 1999
    - last accessed: Sun Sep 19 00:00:00 1999
    - last modified: Sun May 19 01:42:16 1996
    - mode: 0100666
    - inode/dev: 0 2
    
    fstat samples/sample.jpg
    - size: 4762 bytes
    - owner: 0 0
    - created: Tue Sep 07 22:45:58 1999
    - last accessed: Sun Sep 19 00:00:00 1999
    - last modified: Sun May 19 01:42:16 1996
    - mode: 0100666
    - inode/dev: 0 0*b*
    ```
    
    返回对象中有些属性在非 Unix 平台下是无意义的, 比如 (``st_inode`` , ``st_dev``)为 
    Unix 下的为每个文件提供了唯一标识, 但在其他平台可能为任意无意义数据 .
    
    ``stat`` 模块包含了很多可以处理该返回对象的常量及函数. 下面的代码展示了其中的一些. 
    
    可以使用 ``chmod`` 和 ``utime`` 函数修改文件的权限模式和时间属性,如 [Example 1-33 #eg-1-33] 所示. 
    
    ====Example 1-33. 使用 os 模块修改文件的权限和时间戳====[eg-1-33]
    
    ```
    File: os-example-2.py
    
    import os
    import stat, time
    
    infile = "samples/sample.jpg"
    outfile = "out.jpg"
    
    # copy contents
    fi = open(infile, "rb")
    fo = open(outfile, "wb")
    
    while 1:
        s = fi.read(10000)
        if not s:
            break
        fo.write(s)
    
    fi.close()
    fo.close()
    
    # copy mode and timestamp
    st = os.stat(infile)
    os.chmod(outfile, stat.S_IMODE(st[stat.ST_MODE]))
    os.utime(outfile, (st[stat.ST_ATIME], st[stat.ST_MTIME]))
    
    print "original", "=>"
    print "mode", oct(stat.S_IMODE(st[stat.ST_MODE]))
    print "atime", time.ctime(st[stat.ST_ATIME])
    print "mtime", time.ctime(st[stat.ST_MTIME])
    
    print "copy", "=>"
    st = os.stat(outfile)
    print "mode", oct(stat.S_IMODE(st[stat.ST_MODE]))
    print "atime", time.ctime(st[stat.ST_ATIME])
    print "mtime", time.ctime(st[stat.ST_MTIME])
    
    *B*original =>
    mode 0666
    atime Thu Oct 14 15:15:50 1999
    mtime Mon Nov 13 15:42:36 1995
    copy =>
    mode 0666
    atime Thu Oct 14 15:15:50 1999
    mtime Mon Nov 13 15:42:36 1995*b*
    ```
    
    === 处理进程===
    
    ``system`` 函数在当前进程下执行一个新命令, 并等待它完成, 如 [Example 1-34 #eg-1-34] 所示. 
    
    ====Example 1-34. 使用 os 执行操作系统命令====[eg-1-34]
    
    ```
    File: os-example-8.py
    
    import os
    
    if os.name == "nt":
        command = "dir"
    else:
        command = "ls -l"
    
    os.system(command)
    
    *B*-rwxrw-r--   1 effbot  effbot        76 Oct  9 14:17 README
    -rwxrw-r--   1 effbot  effbot      1727 Oct  7 19:00 SimpleAsyncHTTP.py
    -rwxrw-r--   1 effbot  effbot       314 Oct  7 20:29 aifc-example-1.py
    -rwxrw-r--   1 effbot  effbot       259 Oct  7 20:38 anydbm-example-1.py
    ...*b*
    ```
    
    命令通过操作系统的标准 shell 执行, 并返回 shell 的退出状态. 需要注意的是在 Windows 95/98 
    下, shell 通常是 ``command.com`` , 它的推出状态总是 0. 
    
            由于 11os.system11 直接将命令传递给 shell , 所以如果你不检查传入参数的时候会很危险 
            (比如命令 ``os.system("viewer %s" % file)``, 将 file 变量设置为 
            "``sample.jpg; rm -rf $HOME" ....``). 如果不确定参数的安全性, 那么最好使用
            ``exec`` 或 ``spawn`` 代替(稍后介绍).
    
     
    ``exec`` 函数会使用新进程替换当前进程(或者说是"转到进程"). 在 [Example 1-35 #eg-1-35] 中, 
    字符串 "goodbye" 永远不会被打印. 
    
    ====Example 1-35. 使用 os 模块启动新进程====[eg-1-35]
    
    ```
    File: os-exec-example-1.py
    
    import os
    import sys
    
    program = "python"
    arguments = ["hello.py"]
    
    print os.execvp(program, (program,) +  tuple(arguments))
    print "goodbye"
    
    *B*hello again, and welcome to the show*b*
    ```
    
    Python 提供了很多表现不同的 ``exec`` 函数. [Example 1-35 #eg-1-35] 使用的是 
    ``execvp`` 函数, 它会从标准路径搜索执行程序, 把第二个参数(元组)作为单独的参数传递给程序, 并使用当前的环境变量来运行程序. 其他七个同类型函数请参阅 //Python Library Reference// .
    
    在 Unix 环境下, 你可以通过组合使用 ``exec`` , ``fork`` 以及 ``wait`` 函数来从当前程序调用另一个程序, 
    如 [Example 1-36 #eg-1-36] 所示. ``fork`` 函数复制当前进程, ``wait`` 函数会等待一个子进程执行结束. 
    
    ====Example 1-36. 使用 os 模块调用其他程序 (Unix)====[eg-1-36]
    
    ```
    File: os-exec-example-2.py
    
    import os
    import sys
    
    def run(program, *args):
        pid = os.fork()
        if not pid:
            os.execvp(program, (program,) +  args)
        return os.wait()[0]
    
    run("python", "hello.py")
    
    print "goodbye"
    
    *B*hello again, and welcome to the show
    goodbye*b*
    ```
    
    ``fork`` 函数在子进程返回中返回 0 (这个进程首先从 ``fork`` 返回值), 
    在父进程中返回一个非 0 的进程标识符(子进程的 PID ). 也就是说, 
    只有当我们处于子进程的时候 "``not pid``" 才为真. 
    
    ``fork`` 和 ``wait`` 函数在 Windows 上是不可用的, 但是你可以使用 ``spawn`` 函数, 
    如 [Example 1-37 #eg-1-37] 所示. 不过, ``spawn`` 不会沿着路径搜索可执行文件, 
    你必须自己处理好这些. 
    
    ====Example 1-37. 使用 os 模块调用其他程序 (Windows)====[eg-1-37]
    
    ```
    File: os-spawn-example-1.py
    
    import os
    import string
    
    def run(program, *args):
        # find executable
        for path in string.split(os.environ["PATH"], os.pathsep):
            file = os.path.join(path, program) + ".exe"
            try:
                return os.spawnv(os.P_WAIT, file, (file,) + args)
            except os.error:
                pass
        raise os.error, "cannot find executable"
    
    run("python", "hello.py")
    
    print "goodbye"
    
    *B*hello again, and welcome to the show
    goodbye*b*
    ```
    
    ``spawn`` 函数还可用于在后台运行一个程序. [Example 1-38 #eg-1-38] 给 ``run`` 函数添加了一个可选的 
    ``mode`` 参数; 当设置为 ``os.P_NOWAIT`` 时, 这个脚本不会等待子程序结束, 
    默认值 ``os.P_WAIT`` 时 ``spawn`` 会等待子进程结束. 
    
    其它的标志常量还有 ``os.P_OVERLAY`` ,它使得 ``spawn`` 的行为和 ``exec`` 类似, 
    以及 ``os.P_DETACH`` , 它在后台运行子进程, 与当前控制台和键盘焦点隔离. 
    
    ====Example 1-38. 使用 os 模块在后台执行程序 (Windows)====[eg-1-38]
    
    ```
    File: os-spawn-example-2.py
    
    import os
    import string
    
    def run(program, *args, **kw):
        # find executable
        mode = kw.get("mode", os.P_WAIT)
        for path in string.split(os.environ["PATH"], os.pathsep):
            file = os.path.join(path, program) + ".exe"
            try:
                return os.spawnv(mode, file, (file,) + args)
            except os.error:
                pass
        raise os.error, "cannot find executable"
    
    run("python", "hello.py", mode=os.P_NOWAIT)
    print "goodbye"
    
    *B*goodbye
    hello again, and welcome to the show*b*
    ```
    
    [Example 1-39 #eg-1-39] 提供了一个在 Unix 和 Windows 平台上通用的 ``spawn`` 方法. 
    
    ====Example 1-39. 使用 spawn 或 fork/exec 调用其他程序====[eg-1-39]
    
    ```
    File: os-spawn-example-3.py
    
    import os
    import string
    
    if os.name in ("nt", "dos"):
        exefile = ".exe"
    else:
        exefile = ""
    
    def spawn(program, *args):
        try:
            # possible 2.0 shortcut!
            return os.spawnvp(program, (program,) + args)
        except AttributeError:
            pass
        try:
            spawnv = os.spawnv
        except AttributeError:
    
            # assume it's unix
            pid = os.fork()
            if not pid:
                os.execvp(program, (program,) + args)
            return os.wait()[0]
        else:
            # got spawnv but no spawnp: go look for an executable
            for path in string.split(os.environ["PATH"], os.pathsep):
                file = os.path.join(path, program) + exefile
                try:
                    return spawnv(os.P_WAIT, file, (file,) + args)
                except os.error:
                    pass
            raise IOError, "cannot find executable"
    
    #
    # try it out!
    
    spawn("python", "hello.py")
    
    print "goodbye"
    
    *B*hello again, and welcome to the show
    goodbye*b*
    ```
    
    [Example 1-39 #eg-1-39] 首先尝试调用 ``spawnvp`` 函数. 如果该函数不存在
    (一些版本/平台没有这个函数), 它将继续查找一个名为 ``spawnv`` 的函数并且
    开始查找程序路径. 作为最后的选择, 它会调用 ``exec`` 和 ``fork`` 函数完成工作. 
    
    === 处理守护进程(Daemon Processes)===
    
    Unix 系统中, 你可以使用 ``fork`` 函数把当前进程转入后台(一个"守护者/daemon"). 一般来说, 你需要派生(fork off)一个当前进程的副本, 然后终止原进程, 如 [Example 1-40 #eg-1-40] 所示. 
    
    ====Example 1-40. 使用 os 模块使脚本作为守护执行 (Unix)====[eg-1-40]
    
    ```
    File: os-example-14.py
    
    import os
    import time
    
    pid = os.fork()
    if pid:
        os._exit(0) # kill original
    
    print "daemon started"
    time.sleep(10)
    print "daemon terminated"
    ```
    
    需要创建一个真正的后台程序稍微有点复杂, 首先调用 ``setpgrp`` 函数创建一个 "进程组首领/process group leader". 否则, 向无关进程组发送的信号(同时)会引起守护进程的问题: 
    
    ``` os.setpgrp()
    
    为了确保守护进程创建的文件能够获得程序指定的 mode flags(权限模式标记?), 最好删除 user mode mask:
    
    ``` os.umask(0)
    
    然后, 你应该重定向 //stdout/stderr// 文件, 而不能只是简单地关闭它们(如果你的程序需要 ``stdout`` 
    或 ``stderr`` 写入内容的时候, 可能会出现意想不到的问题). 
    
    ```
    class NullDevice:
        def write(self, s):
            pass
    sys.stdin.close()
    sys.stdout = NullDevice()
    sys.stderr = NullDevice()
    ```
    
    换言之, 由于 Python 的 ``print`` 和 C 中的 ``printf/fprintf`` 在设备(device)
    没有连接后不会关闭你的程序, 此时守护进程中的 ``sys.stdout.write()`` 会抛出一个 //IOError// 异常, 而你的程序依然在后台运行的很好.... 
    
    另外, 先前例子中的 ``_exit`` 函数会终止当前进程. 而 ``sys.exit`` 不同, 如果调用者(caller)
    捕获了 //SystemExit// 异常, 程序仍然会继续执行. 如 [Example 1-41 #eg-1-41] 所示.
    
    ====Example 1-41. 使用 os 模块终止当前进程====[eg-1-41]
    
    ```
    File: os-example-9.py
    
    import os
    import sys
    
    try:
        sys.exit(1)
    except SystemExit, value:
        print "caught exit(%s)" % value
    
    try:
        os._exit(2)
    except SystemExit, value:
        print "caught exit(%s)" % value
    
    print "bye!"
    
    *B*caught exit(1)*b*
    ```
  • 相关阅读:
    BZOJ1208
    BZOJ1024
    BZOJ_day4&&DSFZ_day1
    BZOJ day2_plus
    BZOJ day2
    系统设计2:数据库设计
    设计模式8:外观模式
    系统设计1:概述
    设计模式7:模板方法模式
    九章算法班ladder题目梳理
  • 原文地址:https://www.cnblogs.com/xuchunlin/p/7748194.html
Copyright © 2020-2023  润新知