12

I added a build step to execute a Python script.
In this script pylint is called with the lint.Run(..args) to check the code.
The script works but in the end, the build fails with the only error message:

Build step 'Execute Python script' marked build as failure

Someone has an idea why this happens?

9 Answers 9

24

You can also simply put a

pylint || exit 0

in the shell cmdline. The Pylint plugin will fail the build anyway by checking the result of pyllint.

2
  • 3
    The problem with this is that if pylint fails to run, then you'll miss the error as it's still a 0 exit code. Commented Sep 24, 2018 at 15:51
  • using the pipe works but a cleaner solution is given below by sherylpinto & floern stackoverflow.com/questions/7347233/… Commented Sep 7, 2021 at 6:48
16

In Pylint 1.9.3, there is a --exit-zero flag.

https://github.com/PyCQA/pylint/blob/1.9/ChangeLog#L47

14

Pylint has the unpleasant behavior to return a non-zero exit code even only if a small warning issue was found. Only when everything was fine, 0 is returned (see man page).

As usually a non-zero code denotes an error, Jenkins fails the build.

I see two ways to overcome this:

  • Use a small script around pylint that always returns 0. Then jenkins will not fail because of pylint. I use a small python script calling pylint with os.system() and sys.exit(0) after than. You can see it as overriding the error code of pylint.
  • Patch pylint. For example, on my Linux system the sys.exit() call is in the file /usr/lib/pymodules/python2.6/pylint/lint.py
1
  • I piped the output to cat, and it appears to build successfully now. e.g. pylint -f html code.py | cat > report.html
    – zyxue
    Commented Apr 13, 2016 at 3:54
3

it seems that your pylint execution exit with a non-zero status (missing script, bad options...), maybe you exit the script with an exception raised or a sys.exit(something_else_than_zero)

1
  • 1
    Damn straight. I debugged the lint.py and found out about a call sys.exit(self.linter.msgstatus) where the msgstatus could not be found in context. Replacing this with a 0 worked and now the builds are succeding.
    – Gobliins
    Commented Sep 8, 2011 at 12:26
2

Recent rylint have option for not calling sys exit

lint.Run(args, exit=False, **kwargs)
1

Ran into this today (although not using Jenkins).

In my case it was because of how Pylint encodes fatal-error-warning-refactor-convention-usage info in its exit code: https://docs.pylint.org/en/1.6.0/run.html#exit-codes

My fix:

#!/usr/bin/env sh

# Wraps Pylint invocation to produce shell-friendly exit codes
# Because Pylint exit codes are weird:
# https://docs.pylint.org/en/1.6.0/run.html#exit-codes

PYTHON_EXECUTABLE=python
if [ ! -z $PYTHON_ENV ]; then
    PYTHON_EXECUTABLE="$PYTHON_ENV/bin/python"
fi

${PYTHON_EXECUTABLE} -m pylint $@

PYLINT_EXIT_CODE=$?

exit $(($PYLINT_EXIT_CODE % 4))

(Gist: https://gist.github.com/nkashy1/ae59d06d4bf81fb72047fcd390d08903)

1
  • Note: I did not want to use --exit-zero as it doesn't allow me to fail builds when there are legitimate errors (e.g. on undefined-variable errors in Pylint). Commented Aug 26, 2019 at 20:29
1

Pylint expect the code being analyzed to be 100% perfect. Even code warning may cause exit with non zero status code. Try to fix your code as Pylint suggest and rate 10/10.

Hope this helps.

0

I agree with @dmeister, but with pipeline code (Jenkinsfile) I suggest a try/catch and then parsing the error. This way you can determine if you're just getting status bits from pylint (see the Pylint docs), whether pylint reports a usage error, or whether there was a catastrophic fail:

try {       
    sh 'pylint --output-format=parseable my_module'
} catch ( pylint_rc ) {
    // pylint_rc will be of the form
    // "hudson.AbortException: script returned exit code NN"
    // where NN is 1-63 and represents bit field;
    // bits 0-4 indicate lint-ish issues in analyzed code,
    // bit 5 indicates pylint usage error
    echo "pylint_rc= \'$pylint_rc\'"
    String rc = "$pylint_rc"
    String code = rc.split()[5]
    echo "Isolated return code string value $code"
    int value = code.toInteger()

    // catastrophic/crash error returns a 1; else there is a pylint return code
    int error_bits_code = value & 0x20
    int lint_bits_code = value & 0x1f
    echo "pylint error_bits_code=$error_bits_code ; lint_bits_code=$lint_bits_code"
    if ( (value == 1) || (error_bits_code != 0) ) {
        currentBuild.result = "FAILURE"
        throw pylint_rc
    }
}

Apologies to groovy purists - groovy isn't my thing, so I'm sure this can be improved on - let me know. There is one known hole: if pylint detects only "fatal"-type errors (bit 0) and no other issues of any kind (bits 1-4 are not set) then this code will incorrectly throw an exception. But my code flags tons of issues, so that's not a problem for me. The fix (?parse error msg?) might be trivial for someone with groovy chops.

0

The pylint give not zero exit, but without obviously error message. you may need to trace to see which file pylint got failed. and take a look in the file.

For me, I add an empty directory with init.py file, and pylint give same error

Not the answer you're looking for? Browse other questions tagged or ask your own question.