os.pipe() 典型用法:

#!/usr/bin/python

import os, sys

print "The child will write text to a pipe and "
print "the parent will read the text written by child..."

# file descriptors r, w for reading and writing
r, w = os.pipe() 

processid = os.fork()
if processid:
    # This is the parent process 
    # Closes file descriptor w
    os.close(w)
    r = os.fdopen(r)
    print "Parent reading"
    str = r.read()
    print "text =", str
    os.waitpid(processid, 0) # wait for child process terminate
    sys.exit(0)
else:
    # This is the child process
    os.close(r)
    w = os.fdopen(w, 'w')
    print "Child writing"
    w.write("Text written by child...")
    w.close()
    print "Child closing"
    sys.exit(0)
Please note, this usage is only intend for the simplest scenario: The child process need to output something to parent process, and with more complex scenarios, there will be more complex code clips. Will describe this later.

Refer to:http://www.tutorialspoint.com/python/os_pipe.htm and http://jiangzhixiang123.blog.163.com/blog/static/27802062201171105139619/


os.pipe() 的代码实现:

Tracing into module of os (os.py), and find there nothing about function of pipe(), except the following code clips:

_names = sys.builtin_module_names # names of built-in modules, with Windows OS, there will be an item of 'nt' within this tuple, while on Posix (Unix, linux), there will be an item of 'posix' 

# Note:  more names are added to __all__ later.
__all__ = ["altsep", "curdir", "pardir", "sep", "extsep", "pathsep", "linesep",
           "defpath", "name", "path", "devnull",
           "SEEK_SET", "SEEK_CUR", "SEEK_END"]

def _get_exports_list(module): # this function will get all the attributes which not starts with "_"
    try:
        return list(module.__all__)
    except AttributeError:
        return [n for n in dir(module) if n[0] != '_']

if 'posix' in _names:
    name = 'posix'
    linesep = '\n'
    from posix import * # import all the attributes of posix, within which pipe() is implemented as well as other posix system calls
    try:
        from posix import _exit
    except ImportError:
        pass
    import posixpath as path # that's where os.path come from

    import posix
    __all__.extend(_get_exports_list(posix)) # add all the attributes of posix to var __all__
    del posix

We can find that, function of pipe() is implemented within this built-in module posix. Currently will just skip the source code of this.


os.pipe() 的其他用法:


Another scenario of using os.pipe() is subprocess. The following source code comes from subprocess.py

class Popen(object):
    def __init__(self, args, bufsize=0, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=False, shell=False,
                 cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0):
        """Create new Popen instance."""
        _cleanup()

        self._child_created = False
        if not isinstance(bufsize, (int, long)):
            raise TypeError("bufsize must be an integer")

        if mswindows:
            if preexec_fn is not None:
                raise ValueError("preexec_fn is not supported on Windows "
                                 "platforms")
            if close_fds and (stdin is not None or stdout is not None or
                              stderr is not None):
                raise ValueError("close_fds is not supported on Windows "
                                 "platforms if you redirect stdin/stdout/stderr")
        else:
            # POSIX
            if startupinfo is not None:
                raise ValueError("startupinfo is only supported on Windows "
                                 "platforms")
            if creationflags != 0:
                raise ValueError("creationflags is only supported on Windows "
                                 "platforms")

        self.stdin = None
        self.stdout = None
        self.stderr = None
        self.pid = None
        self.returncode = None
        self.universal_newlines = universal_newlines

        # Input and output objects. The general principle is like
        # this:
        #
        # Parent                   Child
        # ------                   -----
        # p2cwrite   ---stdin--->  p2cread
        # c2pread    <--stdout---  c2pwrite
        # errread    <--stderr---  errwrite
        #
        # On POSIX, the child objects are file descriptors.  On
        # Windows, these are Windows file handles.  The parent objects
        # are file descriptors on both platforms.  The parent objects
        # are None when not using PIPEs. The child objects are None
        # when not redirecting.

        (p2cread, p2cwrite,
         c2pread, c2pwrite,
         errread, errwrite) = self._get_handles(stdin, stdout, stderr) # !!!this is what we need 


And we'll see the function self._get_handles() would be like this:

        def _get_handles(self, stdin, stdout, stderr):
            """Construct and return tupel with IO objects:
            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
            """
            p2cread, p2cwrite = None, None
            c2pread, c2pwrite = None, None
            errread, errwrite = None, None

            # stdin can be:
            # None, will inherite from the pareent;
            # a file descirptor, a positive number;
            # a file-object; or
            # PIPE
            if stdin is None:
                pass
            elif stdin == PIPE:
                p2cread, p2cwrite = os.pipe() #p2cread: child process will read input from this end of this pipe, p2cwrite: parent process will write something to pipe with this end. and will be closed by child process.
            elif isinstance(stdin, int):
                p2cread = stdin
            else:
                # Assuming file-like object
                p2cread = stdin.fileno()

            if stdout is None:
                pass
            elif stdout == PIPE:
                c2pread, c2pwrite = os.pipe() # c2pread will be used by parent processto read the output of child process, which will be closed by the child process, while, c2pwrite will be used by child process to output it's outputs to parents
            elif isinstance(stdout, int):
                c2pwrite = stdout
            else:
                # Assuming file-like object
                c2pwrite = stdout.fileno()

            if stderr is None:
                pass
            elif stderr == PIPE:
                errread, errwrite = os.pipe()
            elif stderr == STDOUT: # stderr has another more options of STDOUT.
                errwrite = c2pwrite
            elif isinstance(stderr, int):
                errwrite = stderr
            else:
                # Assuming file-like object
                errwrite = stderr.fileno()

            return (p2cread, p2cwrite,
                    c2pread, c2pwrite,
                    errread, errwrite)

As we can see, if we indicate the parameters of stdin, stdout and stderr to Popen() as PIPE, there will be 3 pipes new created with os.pipe() of which the return values (file descriptors) are assigned to six vars, which will be used and handled by child process.

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐