⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.py

📁 Wxpython Implemented on Windows CE, Source code
💻 PY
📖 第 1 页 / 共 5 页
字号:
        assert errCode == 0,\
               "Why is 'errCode' from ReadFile non-zero? %r" % errCode
        if not text:
            # Empty text signifies that the pipe has been closed on
            # the parent's end.
            log.info("[%s] _FileWrapper.read: observed close of parent",
                     id(self))
            # Signal the child so it knows to stop listening.
            self.close()
            return ""
        else:
            log.info("[%s] _FileWrapper.read: read %d bytes from pipe: %r",
                     id(self), len(text), text)
        return text

    def read(self, nBytes=-1):
        # nBytes <= 0 means "read everything"
        #   Note that we are changing the "read everything" cue to
        #   include 0, because actually doing
        #   win32file.ReadFile(<handle>, 0) results in every subsequent
        #   read returning 0, i.e. it shuts down the pipe.
        if self._descriptor is not None:
            if nBytes <= 0:
                text, self._lineBuf = self._lineBuf, ""
                while 1:
                    t = os.read(self._descriptor, 4092)
                    if not t:
                        break
                    else:
                        text += t
            else:
                if len(self._lineBuf) >= nBytes:
                    text, self._lineBuf =\
                        self._lineBuf[:nBytes], self._lineBuf[nBytes:]
                else:
                    nBytesToGo = nBytes - len(self._lineBuf)
                    text = self._lineBuf + os.read(self._descriptor,
                                                   nBytesToGo)
                    self._lineBuf = ""
            return text
        elif self._handle is not None:
            if nBytes <= 0:
                text, self._lineBuf = self._lineBuf, ""
                while 1:
                    t = self._win32Read(4092)
                    if not t:
                        break
                    else:
                        text += t
            else:
                if len(self._lineBuf) >= nBytes:
                    text, self._lineBuf =\
                        self._lineBuf[:nBytes], self._lineBuf[nBytes:]
                else:
                    nBytesToGo = nBytes - len(self._lineBuf)
                    text, self._lineBuf =\
                        self._lineBuf + self._win32Read(nBytesToGo), ""
            return text
        elif self._file is not None:
            return self._file.read(nBytes)
        else:   
            raise "FileHandle.read: no handle to read with"

    def readline(self):
        if self._descriptor is not None or self._handle is not None:
            while 1:
                #XXX This is not portable to the Mac.
                idx = self._lineBuf.find('\n')
                if idx != -1:
                    line, self._lineBuf =\
                        self._lineBuf[:idx+1], self._lineBuf[idx+1:]
                    break
                else:
                    lengthBefore = len(self._lineBuf)
                    t = self.read(4092)
                    if len(t) <= lengthBefore: # no new data was read
                        line, self._lineBuf = self._lineBuf, ""
                        break
                    else:
                        self._lineBuf += t
            return line
        elif self._file is not None:
            return self._file.readline()
        else:
            raise "FileHandle.readline: no handle to read with"

    def readlines(self):
        if self._descriptor is not None or self._handle is not None:
            lines = []
            while 1:
                line = self.readline()
                if line:
                    lines.append(line)
                else:
                    break
            return lines
        elif self._file is not None:
            return self._file.readlines()
        else:
            raise "FileHandle.readline: no handle to read with"

    def write(self, text):
        if self._descriptor is not None:
            os.write(self._descriptor, text)
        elif self._handle is not None:
            try:
                errCode, nBytesWritten = win32file.WriteFile(self._handle, text)
            except pywintypes.error, ex:
                # Ingore errors like "The pipe is being closed.", for
                # now.
                log.info("[%s] _FileWrapper.write: error writing to pipe, "\
                         "ignored", id(self))
                return
            assert errCode == 0,\
                   "Why is 'errCode' from WriteFile non-zero? %r" % errCode
            if not nBytesWritten:
                # No bytes written signifies that the pipe has been
                # closed on the child's end.
                log.info("[%s] _FileWrapper.write: observed close of pipe",
                         id(self))
                return
            else:
                log.info("[%s] _FileWrapper.write: wrote %d bytes to pipe: %r",
                         id(self), len(text), text)
        elif self._file is not None:
            self._file.write(text)
        else:   
            raise "FileHandle.write: nothing to write with"

    def close(self):
        """Close all associated file objects and handles."""
        log.debug("[%s] _FileWrapper.close()", id(self))
        if not self._closed:
            self._closed = 1
            if self._file is not None:
                log.debug("[%s] _FileWrapper.close: close file", id(self))
                self._file.close()
                log.debug("[%s] _FileWrapper.close: done file close", id(self))
            if self._descriptor is not None:
                try:
                    os.close(self._descriptor)
                except OSError, ex:
                    if ex.errno == 9:
                        # Ignore: OSError: [Errno 9] Bad file descriptor
                        # XXX *Should* we be ignoring this? It appears very
                        #     *in*frequently in test_wait.py.
                        log.debug("[%s] _FileWrapper.close: closing "\
                                  "descriptor raised OSError", id(self))
                    else:
                        raise
            if self._handle is not None:
                log.debug("[%s] _FileWrapper.close: close handle", id(self))
                try:
                    win32api.CloseHandle(self._handle)
                except win32api.error:
                    log.debug("[%s] _FileWrapper.close: closing handle raised",
                              id(self))
                    pass
                log.debug("[%s] _FileWrapper.close: done closing handle",
                          id(self))

    def __repr__(self):
        return "<_FileWrapper: file:%r fd:%r os_handle:%r>"\
               % (self._file, self._descriptor, self._handle)


class _CountingCloser:
    """Call .close() on the given object after own .close() is called
    the precribed number of times.
    """
    def __init__(self, objectsToClose, count):
        """
        "objectsToClose" is a list of object on which to call .close().
        "count" is the number of times this object's .close() method
            must be called before .close() is called on the given objects.
        """
        self.objectsToClose = objectsToClose
        self.count = count
        if self.count <= 0:
            raise ProcessError("illegal 'count' value: %s" % self.count)

    def close(self):
        self.count -= 1
        log.debug("[%d] _CountingCloser.close(): count=%d", id(self),
                  self.count)
        if self.count == 0:
            for objectToClose in self.objectsToClose:
                objectToClose.close()



#---- public interface

class Process:
    """Create a process.

    One can optionally specify the starting working directory, the
    process environment, and std handles to have the child process
    inherit (all defaults are the parent's current settings). 'wait' and
    'kill' method allow for control of the child's termination.
    """
    # TODO:
    #   - Rename this or merge it with ProcessOpen somehow.
    #
    if sys.platform.startswith("win"):
        # .wait() argument constants
        INFINITE = win32event.INFINITE
        # .wait() return error codes
        WAIT_FAILED = win32event.WAIT_FAILED
        WAIT_TIMEOUT = win32event.WAIT_TIMEOUT
        # creation "flags" constants
        # XXX Should drop these and just document usage of
        #     win32process.CREATE_* constants on windows.
        CREATE_NEW_CONSOLE = win32process.CREATE_NEW_CONSOLE
    else:
        # .wait() argument constants
        INFINITE = 0
        # .wait() return error codes
        WAIT_TIMEOUT = 258
        WAIT_FAILED = -1
        # creation "flags" constants
        CREATE_NEW_CONSOLE = 0x10 # same as win32process.CREATE_NEW_CONSOLE

    def __init__(self, cmd, cwd=None, env=None, flags=0):
        """Create a child process.

        "cmd" is a command string or argument vector to spawn.
        "cwd" is a working directory in which to start the child process.
        "env" is an environment dictionary for the child.
        "flags" are system-specific process creation flags. On Windows
            this can be a bitwise-OR of any of the win32process.CREATE_*
            constants (Note: win32process.CREATE_NEW_PROCESS_GROUP is always
            OR'd in). On Unix, this is currently ignored.
        """
        log.info("Process.__init__(cmd=%r, cwd=%r, env=%r, flags=%r)",
                 cmd, cwd, env, flags)
        self._cmd = cmd
        if not self._cmd:
            raise ProcessError("You must specify a command.")
        self._cwd = cwd
        self._env = env
        self._flags = flags
        if sys.platform.startswith("win"):
            self._flags |= win32process.CREATE_NEW_PROCESS_GROUP

        if sys.platform.startswith("win"):
            self._startOnWindows()
        else:
            self.__retvalCache = None
            self._startOnUnix()

    def _runChildOnUnix(self):
        #XXX Errors running the child do *not* get communicated back.

        #XXX Perhaps we should *always* prefix with '/bin/sh -c'? There is a
        #    disparity btwn how this works on Linux and Windows.
        if isinstance(self._cmd, types.StringTypes):
            # This is easier than trying to reproduce shell interpretation to
            # separate the arguments.
            cmd = ['/bin/sh', '-c', self._cmd]
        else:
            cmd = self._cmd

        # Close all file descriptors (except std*) inherited from the parent.
        MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???)
        for i in range(3, MAXFD):
            try:
                os.close(i)
            except OSError:
                pass

        try:
            if self._env:
                os.execvpe(cmd[0], cmd, self._env)
            else:
                os.execvp(cmd[0], cmd)
        finally:
            os._exit(1)  # Should never get here.

    def _forkAndExecChildOnUnix(self):
        """Fork and start the child process.

        Sets self._pid as a side effect.
        """
        pid = os.fork()
        if pid == 0: # child
            self._runChildOnUnix()
        # parent
        self._pid = pid

    def _startOnUnix(self):
        if self._cwd:
            oldDir = os.getcwd()
            try:
                os.chdir(self._cwd)
            except OSError, ex:
                raise ProcessError(msg=str(ex), errno=ex.errno)
        self._forkAndExecChildOnUnix()

        # parent
        if self._cwd:
            os.chdir(oldDir)

    def _startOnWindows(self):
        if type(self._cmd) in (types.ListType, types.TupleType):
            # And arg vector was passed in.
            cmd = _joinArgv(self._cmd)
        else:
            cmd = self._cmd

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -