Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How to parse a "return" string

Tags:

python

parsing

I'm writing a little tool which uses an existing framework via import.

The part I'm using is:

def exec_command(self, command, timeout=60, mode=cli.CLIMode.UNDEF,
                     output_expected=None, error_expected=False, prompt=None):
        """Executes the given command.

        This method handles detecting simple boolean conditions such as
        the presence of output or errors.

        :param command:  command to execute, newline appended automatically
        :param timeout:  maximum time, in seconds, to wait for the command to
            finish. 0 to wait forever.
        :param mode:  mode to enter before running the command. The default
            is :func:`default_mode`.  To skip this step and execute directly
            in the cli's current mode, explicitly set this parameter to None.
        :param output_expected: If not None, indicates whether output is
            expected (True) or no output is expected (False).
            If the opposite occurs, raise UnexpectedOutput. Default is None.
        :type output_expected: bool or None
        :param error_expected: If true, cli error output (with a leading '%')
            is expected and will be returned as regular output instead of
            raising a CLIError.  Default is False, and error_expected always
            overrides output_expected.
        :type error_expected: bool
        :param prompt: Prompt regex for matching unusual prompts.  This should
            almost never be used as the ``mode`` parameter automatically
            handles all typical cases.  This parameter is for unusual
            situations like the install config wizard.

        :return: output of the command, minus the command itself.

        :raises CmdlineTimeout: on timeout
        :raises CLIError: if the output matches the cli's error format, and
            error output was not expected.
        :raises UnexpectedOutput: if output occurs when no output was
            expected, or no output occurs when output was expected
        """

        if output_expected is not None and type(output_expected) is not bool:
            raise TypeError("exec_command: output_expected requires a boolean "
                            "value or None")

        if mode is cli.CLIMode.UNDEF:
            mode = self.default_mode
        if mode is not None:
            self.enter_mode(mode)

        self._log.debug('Executing cmd "%s"' % command)

        if prompt is None:
            prompt = self._prompt
        (output, match_res) = self._send_line_and_wait(command,
                                                       prompt,
                                                       timeout=timeout)

        # CLI adds on escape chars and such sometimes and the result is that
        # some part of the command that was entered shows up as an extra
        # initial line of output.  Strip off that initial line.
        output = '\n'.join(output.splitlines()[1:])

        if output and (re.match(self.CLI_ERROR_PROMPT, output)):
            if error_expected:
                # Skip output_expected processing entirely.
                return output
            else:
                try:
                    mode = self.current_cli_mode()
                except exceptions.UnknownCLIMode:
                    mode = '<unrecognized>'
                raise exceptions.CLIError(command, output=output, mode=mode)

        if ((output_expected is not None) and (bool(output) !=
                                               bool(output_expected))):
            raise exceptions.UnexpectedOutput(command=command,
                                              output=output,
                                              expected_output=output_expected)
        return output

I'm using in my script:

print sh.cli.exec_command(command, mode="enable")

this works perfectly fine. The tool is logging into the appliance, executing the command. According to the framework it's "return" is ":return: output of the command, minus the command itself." This also works fine, when the command is executed, I get:

Generated dump sysdump-csh-20150320-140445.tgz

Perfect! For the next step, I need the name of the dump created, i.e. the return string without the "Generated dump " text.

Now I'm struggling in parsing that into a new variable I can use to e.g. download the generated dump and delete it afterwards, etc.

like image 590
f0rd42 Avatar asked Apr 15 '26 00:04

f0rd42


1 Answers

s = "Generated dump sysdump-csh-20150320-140445.tgz"
print s.split()[-1]

Yields

"sysdump-csh-20150320-140445.tgz"

This is just parsing by splitting on whitespace. Every parsing decision depends on some assumptions. This one depends on the assumption that the file name you want will be contiguous (no internal spaces), and the the last item on a whitespace-split list.

Martijn Pieters beat me to the improved formulation of this:

s.split(None, 2)[-1]

Or even better:

s.strip().split(None, 2)[-1]

This is the best because it doesn't also assume that the file name is contiguous. The .strip() also removes the assumption that there are no trailing spaces.

Keep in mind that whatever simple parsing strategy you choose, it's always dependent on assumptions. Even with the improved formulation here, for instance, we still assume the file name is the last item on the line. If the program producing this line were updated to "Generated dump sysdump-csh-20150320-140445.tgz on March 20, 2015." say, we'd have to finagle it yet another way.

like image 152
Jonathan Eunice Avatar answered Apr 16 '26 15:04

Jonathan Eunice



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!