def main(argv=None):
    """
    A simple command-line interface for the runexecutor module of BenchExec.
    """
    if argv is None:
        argv = sys.argv

    # parse options
    parser = argparse.ArgumentParser(
        fromfile_prefix_chars='@',
        description=
        """Execute a command with resource limits and measurements.
           Command-line parameters can additionally be read from a file if file name prefixed with '@' is given as argument.
           Part of BenchExec: https://github.com/sosy-lab/benchexec/""")

    resource_args = parser.add_argument_group("optional arguments for resource limits")
    resource_args.add_argument("--memlimit", type=util.parse_memory_value, metavar="BYTES",
        help="memory limit in bytes")
    resource_args.add_argument("--timelimit", type=util.parse_timespan_value, metavar="SECONDS",
        help="CPU time limit in seconds")
    resource_args.add_argument("--softtimelimit", type=util.parse_timespan_value, metavar="SECONDS",
        help='"soft" CPU time limit in seconds (command will be send the TERM signal at this time)')
    resource_args.add_argument("--walltimelimit", type=util.parse_timespan_value, metavar="SECONDS",
        help='wall time limit in seconds (default is CPU time limit plus a few seconds)')
    resource_args.add_argument("--cores", type=util.parse_int_list, metavar="N,M-K",
        help="list of CPU cores to use")
    resource_args.add_argument("--memoryNodes", type=util.parse_int_list, metavar="N,M-K",
        help="list of memory nodes to use")

    io_args = parser.add_argument_group("optional arguments for run I/O")
    io_args.add_argument("--input", metavar="FILE",
        help="name of file used as stdin for command "
            "(default: /dev/null; use - for stdin passthrough)")
    io_args.add_argument("--output", default="output.log", metavar="FILE",
        help="name of file where command output is written")
    io_args.add_argument("--maxOutputSize", type=util.parse_memory_value, metavar="BYTES",
        help="shrink output file to approximately this size if necessary "
            "(by removing lines from the middle of the output)")
    io_args.add_argument("--skip-cleanup", action="store_false", dest="cleanup",
        help="do not delete files created by the tool in temp directory")

    environment_args = parser.add_argument_group("optional arguments for run environment")
    environment_args.add_argument("--require-cgroup-subsystem", action="append", default=[], metavar="SUBSYSTEM",
        help="additional cgroup system that should be enabled for runs "
            "(may be specified multiple times)")
    environment_args.add_argument("--set-cgroup-value", action="append", dest="cgroup_values", default=[],
        metavar="SUBSYSTEM.OPTION=VALUE",
        help="additional cgroup values that should be set for runs (e.g., 'cpu.shares=1000')")
    environment_args.add_argument("--dir", metavar="DIR",
        help="working directory for executing the command (default is current directory)")
    environment_args.add_argument("--user", metavar="USER",
        help="execute tool under given user account (needs password-less sudo setup)")

    baseexecutor.add_basic_executor_options(parser)

    options = parser.parse_args(argv[1:])
    baseexecutor.handle_basic_executor_options(options)

    # For integrating into some benchmarking frameworks,
    # there is a DEPRECATED special mode
    # where the first and only command-line argument is a serialized dict
    # with additional options
    env = {}
    if len(options.args) == 1 and options.args[0].startswith("{"):
        data = eval(options.args[0])
        options.args = data["args"]
        env = data.get("env", {})
        options.debug = data.get("debug", options.debug)
        if data in "maxLogfileSize":
            try:
                options.maxOutputSize = int(data["maxLogfileSize"]) * _BYTE_FACTOR * _BYTE_FACTOR # MB to bytes
            except ValueError:
                options.maxOutputSize = util.parse_memory_value(data["maxLogfileSize"])

    if options.input == '-':
        stdin = sys.stdin
    elif options.input is not None:
        if options.input == options.output:
            parser.error("Input and output files cannot be the same.")
        try:
            stdin = open(options.input, 'rt')
        except IOError as e:
            parser.error(e)
    else:
        stdin = None

    cgroup_subsystems = set(options.require_cgroup_subsystem)
    cgroup_values = {}
    for arg in options.cgroup_values:
        try:
            key, value = arg.split("=", 1)
            subsystem, option = key.split(".", 1)
            if not subsystem or not option:
                raise ValueError()
        except ValueError:
            parser.error(
                'Cgroup value "{}" has invalid format, needs to be "subsystem.option=value".'
                    .format(arg))
        cgroup_values[(subsystem, option)] = value
        cgroup_subsystems.add(subsystem)

    executor = RunExecutor(user=options.user, cleanup_temp_dir=options.cleanup,
                           additional_cgroup_subsystems=list(cgroup_subsystems))

    # ensure that process gets killed on interrupt/kill signal
    def signal_handler_kill(signum, frame):
        executor.stop()
    signal.signal(signal.SIGTERM, signal_handler_kill)
    signal.signal(signal.SIGINT,  signal_handler_kill)

    formatted_args = " ".join(map(util.escape_string_shell, options.args))
    logging.info('Starting command %s', formatted_args)
    logging.info('Writing output to %s', options.output)

    # actual run execution
    try:
        result = executor.execute_run(
                            args=options.args,
                            output_filename=options.output,
                            stdin=stdin,
                            hardtimelimit=options.timelimit,
                            softtimelimit=options.softtimelimit,
                            walltimelimit=options.walltimelimit,
                            cores=options.cores,
                            memlimit=options.memlimit,
                            memory_nodes=options.memoryNodes,
                            cgroupValues=cgroup_values,
                            environments=env,
                            workingDir=options.dir,
                            maxLogfileSize=options.maxOutputSize)
    finally:
        if stdin:
            stdin.close()

    executor.check_for_new_files_in_home()

    # exit_code is a special number:
    exit_code = util.ProcessExitCode.from_raw(result['exitcode'])

    def print_optional_result(key):
        if key in result:
            # avoid unicode literals such that the string can be parsed by Python 3.2
            print(key + "=" + str(result[key]).replace("'u", ''))

    # output results
    print_optional_result('terminationreason')
    print("exitcode=" + str(exit_code.raw))
    if exit_code.value is not None:
        print("returnvalue=" + str(exit_code.value))
    if exit_code.signal is not None:
        print("exitsignal=" + str(exit_code.signal))
    print("walltime=" + str(result['walltime']) + "s")
    print("cputime=" + str(result['cputime']) + "s")
    for key in sorted(result.keys()):
        if key.startswith('cputime-'):
            print("{}={:.9f}s".format(key, result[key]))
    print_optional_result('memory')
    if 'energy' in result:
        for key, value in result['energy'].items():
            print("energy-{0}={1}".format(key, value))
dataset/ETHPy150Open sosy-lab/benchexec/benchexec/runexecutor.py/main/swapped operands of `in`