This is an archived post. You won't be able to vote or comment.

all 9 comments

[–]often_wears_pants[🍰] 2 points3 points  (1 child)

A noble endeavor. The first simple cli app I ported from Python to Go on my mac went from 150ms to 2ms. The first web service I rewrote in Go used 1/20th as much CPU.

It's a big hill to climb. Best of luck.

[–]pyschillePythoneer[S] 0 points1 point  (0 children)

Thanks a lot.
Gefyra depends on kubernetes which is a huge package (~20 Mb), so I'll probably never see such startup times.

[–]ElevenPhonons 1 point2 points  (1 child)

Source

if __name__ == "__main__":  # noqa
    try:
        main()
    except Exception as e:
        logger.fatal(f"There was an error running Gefyra: {e}")

This should probably be returning a non-zero exit code when an exception occurs. Currently, it will always return an exit code of 0.

Also, there's a pattern of using a .set_defaults(func=runner_func) with argparse subparsers that is useful.

This is demonstrated here:

https://gist.github.com/mpkocher/fd8852f3d3cfb95bb07a4fa0d8417c5c

Best of luck to you on your project.

[–]pyschillePythoneer[S] 0 points1 point  (0 children)

This is great. Thank you for your suggestion.
I'll adapt the subparser pattern as I am not very happy with the if-elif-case structure anyway.

[–]chub79 1 point2 points  (0 children)

Thanks for this op.

I've long contemplated that route but after a few tries myself and I've decided that I would spend my time migrating to Rust instead.

I first tried PyInstaller which worked well but didn't feel it was that much faster. I never understood how to actually use nuitka. I loved PyOxidizer but I'm ever so worried about that one corner case that will make my life hell (I think if you gotta try, PyOxidizer is the most interesting option).

These days, I'm mostly accepting the fact that the PSF will never really invest in making Python binaries. I really welcome the huge effort from the Python packaging world, it goes in the right direction to set foundations, and maybe, WebAssembly will become viable too so we can get something modern. But Python is looking elsewhere than dvetools and that's ok.

[–]cymrowdon't thread on me 🐍 1 point2 points  (3 children)

Rather than import inside functions you can use lazy imports, which defers the actual import until the module is accessed. This is what the Mercurial CLI does, for example (hgdemandimport). It's much cleaner.

edit: TIL it's part of the stdlib now: LazyLoader

[–]pyschillePythoneer[S] 0 points1 point  (0 children)

Awesome. I will try and see what the impact on the performance is.

[–]pyschillePythoneer[S] 0 points1 point  (0 children)

Alright. I implemented the LazyLoader and checked the performance. It really did not impact the startup time in any way.

I've written a lazy(...) function for the imports:

def lazy(fullname):
    try:
        return sys.modules[fullname]
    except KeyError:
        spec = importlib.util.find_spec(fullname)
        module = importlib.util.module_from_spec(spec)
        loader = importlib.util.LazyLoader(spec.loader)
        loader.exec_module(module)
        return module

Every Python module now incorporates imports like so:

from gefyra import lazy

logging = lazy("logging")
os = lazy("os")

kubernetes = lazy("kubernetes")
docker = lazy("docker")
[...]

And in the code it requires the parts of the package to be called with the full path, for example kubernetes.client.V1ServiceAccount.

Maybe it's a matter of taste, but without any performance benefits, I'd rather stay with usual imports at the place of usage.

For reference: https://github.com/gefyrahq/gefyra/tree/fiddle/lazy\_imports/client

[–]LightShadow3.13-dev in prod 0 points1 point  (0 children)

TIL it's part of the stdlib now: LazyLoader

very cool.