Exection of Python package using Python entrypoint convention not working in Octopus environment

I suspect this is an issue due to the way how Calamari starts the Python process.

Background:
One can call python scripts via command line (e.g. using inline PowerShell) as python $PathToScript. Using the native Python option I expect the same result. This works fine for simple Python packages in Octopus but not for one special case, the native Python execution does not work:

REPRO:
Create a package with the following content (let’s call it main.py but the name does not matter here, I could’ve also called it foo.py)

def foo():
    print("Hello")

if __name__ == '__main__':
    foo()

Python has this convention whereby __name__ is defined as __main__ and you will see this works fine when executing python $PathToScript locally in your shell of choice or in Octopus using inline PowerShell. However, when using the Script file in package option and pointing it to main.py, this does not work. Since all other Python files execute fine using this option, I’d consider this a bug. The impact is quite high because there are libraries that require end users to use such a convention, as a result, the only way to use Python from such a package is to call python $ScriptPath via PowerShell but this completely defeats the point of the native Octopus integration and we do not get live streaming of stdout/stderr, etc.

I am using Octopus 2019.6.7 (LTS) and Calamari 6.0.0

Hi @Christoph.Bergmeister,

Thanks for getting in touch! I’ll start by saying, I’m not a python expert. :slight_smile:

What I can explain is how we invoke your python scripts. We use runpy.run_path to execute your python script. We do this so we can deliver Octopus Variables into your script file.

Here is the documentation on runpy which mentions these global variables: https://docs.python.org/3/library/runpy.html

And here is the code we use to bootstrap and execute your python script: https://github.com/OctopusDeploy/Calamari/blob/master/source/Calamari.Shared/Integration/Scripting/Python/PythonBootstrapper.cs

Hopefully that gives you enough context to help me understand whether:

  1. You can execute your scripts in a slightly different way
  2. We can offer some kind of enhancement to enable your scripts to “just work” within an Octopus world
  3. There is some kind of compromise between these options

Hope that helps!
Mike

@Michael_Noonan Thanks for the detailed info and the link to runpy and the source code where I could see that I calls runpy.run_path with only 1 argument. With that I could create a simple test script to reproduce and experiment:

from runpy import run_path
run_path("C:\\Users\\myusername\\main\\main.py")

As per documentation of runpy the value of __name__ is <run_path> in this case and not __main__. I could confirm this by adapting the test package, which works now:

def foo():
    print("Hello")

print(__name__)

if __name__ == '<run_path>':
    foo()

However, I’d still expect some issues later down the road as I suspect some other 3rd party Python packages have the if __name__ == '__main__' convention hard-coded in them. It would be great if Octopus had a link to runpy in its docs. It might be useful to optionally call run_path with 3 arguments (maybe a configuration option in the Octopus task) and pass the value of run_name. For the moment, I cannot say yet this will cause an issue further down the road for us but it’s something you guys might want to discuss internally.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.