Question

Re-usable Utility Methods in Functions in Python

I read the question answered by Rodric Rabbah, and worked through his ‘pymod’ example. All is well, but I need to take that to the next level.

I want to make a method that is called by multiple DO Functions.

I have taken two different approaches, each failing for it’s own reason. Happy to just use whatever works.

Single File

My first attempt was using a single file with multiple Function entry points.

Under packages/tom/ I have the file tomsfns.py code follows:

def t1():
    return { "body", make_msg("T1") }

def t2():
    return { "body", make_msg("T2") }

def make_msg(caller):
    return "Hello " + caller

Dumb as toast, but should work fine. Under packages in the project.yml I have the following:

  - name: tom
    functions:
      - name: tomsfns
        main: t1
        binary: false
        runtime: python:3.11
        web: false

      - name: tomsfns
        main: t2
        binary: false
        runtime: python:3.11
        web: false

What that does is deploys a Function called tom/tomsfns and the entirety of the code is in that single function. What I hoped for was two Functions off the same codebase.

Multi File

My second attempt was was to break out the desired utility into it’s own python file and then have separate files call it. This is the ‘style’ that makes the most sense to me but doesn’t work either.

Both the structure and the contents are:

packages
    rick
        r1.py
             import make_msg
             def main():
                return { "body": make_msg("R1") }
        r2.py
             import make_msg
             def main():
                return { "body": make_msg("R2") }
        rickutils.py
             def make_msg(caller):
                return "Hello " + caller

The relevant project.yml is:

  - name: rick
    functions:
      - name: r1
        runtime: python:3.11
        web: false

      - name: r2
        runtime: python:3.11
        web: false

This results in what appears to be the right structure and code in the published functions:

Deployed functions ('doctl sls fn get <funcName> --url' for URL):
  - rick/r1
  - rick/r2
  - rick/rickutils
  - tom/tomsfns

However a) I didn’t want rickutils as a function and more importantly b) the functions do not run.

stderr: Invalid function: No module named 'make_msg

I have tried every combination of import statement to get that method into the Function code but nothing has worked.

Does anybody have any thoughts or examples of this kind of thing?

Thanks.


Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

It looks like you’re trying to create multiple serverless functions that share a common utility function make_msg. In your multi-file approach, you’re encountering issues with module imports and the structure of your project. Let’s address these issues and provide a solution.

  1. Module Import Issue: The error message No module named 'make_msg' suggests that Python can’t find the make_msg module. You need to ensure that the module is importable. In Python, to import a function from another file, you should use the import statement with the file/module name (without the .py extension).

    Modify your rick/r1.py and rick/r2.py as follows: from rickutils import make_msg

def main(): return {“body”: make_msg(“R1”)} from rickutils import make_msg

def main(): return {“body”: make_msg(“R2”)}

2 Shared Utility Function: In your multi-file approach, you don’t need to deploy rickutils as a separate function. Instead, keep it as a Python module (.py file) within your project structure.

The project structure should look like this: packages/ ├── rick/ │ ├── r1.py │ └── r2.py └── rickutils.py You only need to include rick functions in your project.yml:

  • name: rick functions:
    • name: r1 runtime: python:3.11 web: false

    • name: r2 runtime: python:3.11 web: false

  • name: rick functions:
    • name: r1 runtime: python:3.11 web: false

    • name: r2 runtime: python:3.11 web: false

  1. There’s no need to include rickutils in the project.yml as it’s just a module that will be automatically available to the functions in the rick package.

With these changes, you should have two separate functions rick/r1 and rick/r2 that use the shared utility function make_msg without any import issues. Your project structure and deployment setup will be cleaner as well.

Hope it will help.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel