FileNotFoundError while snapping Python program

I’m trying to get the hang of snapping python programs and packages, and I am running into this impassible error.

Sorry, an error occurred in Snapcraft:                                                                                
Traceback (most recent call last):                                                                                    
  File "/usr/bin/snapcraft", line 11, in <module>                                                                     
    load_entry_point('snapcraft==2.43.1+18.4', 'console_scripts', 'snapcraft')()                                      
  File "/usr/lib/python3/dist-packages/click/core.py", line 722, in __call__                                          
    return self.main(*args, **kwargs)                                                                                 
  File "/usr/lib/python3/dist-packages/click/core.py", line 697, in main                                              
    rv = self.invoke(ctx)                                                                                             
  File "/usr/lib/python3/dist-packages/click/core.py", line 1043, in invoke                                           
    return Command.invoke(self, ctx)                                                                                  
  File "/usr/lib/python3/dist-packages/click/core.py", line 895, in invoke                                            
    return ctx.invoke(self.callback, **ctx.params)                                                                    
  File "/usr/lib/python3/dist-packages/click/core.py", line 535, in invoke                                            
    return callback(*args, **kwargs)                                                                                  
  File "/usr/lib/python3/dist-packages/click/decorators.py", line 17, in new_func                                     
    return f(get_current_context(), *args, **kwargs)                                                                  
  File "/usr/lib/python3/dist-packages/snapcraft/cli/_runner.py", line 93, in run                                     
    ctx.forward(lifecyclecli.commands["snap"])                                                                        
  File "/usr/lib/python3/dist-packages/click/core.py", line 553, in forward                                           
    return self.invoke(cmd, **kwargs)                                                                                 
  File "/usr/lib/python3/dist-packages/click/core.py", line 535, in invoke                                            
    return callback(*args, **kwargs)                                                                                  
  File "/usr/lib/python3/dist-packages/snapcraft/cli/lifecycle.py", line 136, in snap                                 
    project = _execute(steps.PRIME, parts=[], **kwargs)                                                               
  File "/usr/lib/python3/dist-packages/snapcraft/cli/lifecycle.py", line 35, in _execute                              
    lifecycle.execute(step, project_config, parts)                                                                    
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_runner.py", line 90, in execute                  
    executor.run(step, part_names)                                                                                    
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_runner.py", line 196, in run                     
    self._create_meta(step, processed_part_names)                                                                     
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle/_runner.py", line 359, in _create_meta            
    self.config.validator.schema,                                                                                     
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta/_snap_packaging.py", line 109, in create_snap_packaging
    packaging.write_snap_yaml()                                                                                       
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta/_snap_packaging.py", line 312, in write_snap_yaml      
    snap_yaml = self._compose_snap_yaml()                                                                             
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta/_snap_packaging.py", line 468, in _compose_snap_yaml   
    snap_yaml["apps"] = self._wrap_apps(self._config_data["apps"])                                                    
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta/_snap_packaging.py", line 567, in _wrap_apps           
    self._wrap_app(app, apps[app])                                                                                    
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta/_snap_packaging.py", line 575, in _wrap_app            
    app[k] = self._wrap_exe(app[k], "{}-{}".format(k, name))                                                          
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta/_snap_packaging.py", line 546, in _wrap_exe            
    with open(exepath, "rb") as exefile:                                                                              
FileNotFoundError: [Errno 2] No such file or directory: '/home/wnilges/Documents/cryptotest/prime/bin/crypto_test'    
We would appreciate it if you created a bug report at                                                                 
https://launchpad.net/snapcraft/+filebug with the above text included.                                                

The important part is this: FileNotFoundError: [Errno 2] No such file or directory: '/home/wnilges/Documents/cryptotest/prime/bin/crypto_test'

I tried following this guide to get everything up and running, but I am thoroughly confused by this setuptools nonsense.

The only other thing in the directory is bin/crypto_test, the contents of which are

#!/usr/bin/env Python
                     
print("Hello world!")

and setup.py

from setuptools import setup, find_packages
setup(                                     
    name="crypto-test",                    
    version="0.1",                         
    packages=find_packages(),              
)                                         

Which I only have because the tutorial told me to.

Here’s my /snap/snapcraft.yaml.

name: crypto-test # you probably want to 'snapcraft register <name>'            
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'                
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
base: core18                                                                    
description: |                                                                  
  This is my-snap's description. You have a paragraph or two to tell the        
  most important story about your snap. Keep it under 100 words though,         
  we live in tweetspace and your description wants to look good in the snap     
  store.                                                                        
                                                                                
grade: devel # must be 'stable' to release into candidate/stable channels       
confinement: devmode # use 'strict' once you have the right plugs and slots     
                                                                                
parts:                                                                          
    crypto-test:                                                                
        source: .                                                               
        # See 'snapcraft plugins'                                               
        plugin: python                                                          
        python-version: 'python3'                                               
        python-packages:                                                        
            - cryptoauthlib                                                     
            - setuptools                                                        
                                                                                
apps:                                                                           
    crypto-test:                                                                
        command: bin/crypto_test                                                

Your setup.py is incomplete. You should add an entry_points config to it. The Python docs should explain how to do this. It is not a problem with Snapcraft, just that Snapcraft is highlighting it.

1 Like

Something like this?

setup(
    # ...
    entry_points={
        "distutils.commands": [
            "foo = mypackage.some_module:foo",
        ],
    },
)

So if I just wanted my package to execute my script, I’d do something like

setup(
    # ...
    entry_points={
        "distutils.commands": [
            "crypto-test = crypto-test",
        ],
    },
)

?

So I updated my setup.py like so, to include the script:

from setuptools import setup, find_packages
setup(                                     
    name="crypto-test",                    
    version="0.1",                         
    packages=find_packages(),              
    scripts = ['bin/crypto_test'],         
                                           
)                                          

and then I got this error while priming
Failed to run '/bin/sh /tmp/tmpk_3jgnae': Exited with code 1.

This is what I have in my fakecam project’s setup.py:

    entry_points={
        'console_scripts': [
            'fakecamcli=fakecam.cli:main',
            'fakecamgui=fakecam.gui:main',
        ],
    },

The two scripts are cli.py and gui.py in a folder called fakecam, which also has an __init__.py to indicate that it is a module folder. Those python scripts include a main function as indicated by the console_scripts entry above.

I also have, alongside the setup.py two simple scripts which allow me to execute the main functions in the respective files for testing without snapping it up. Those have the contents similar to:

from fakecam.gui import main
# or `from fakecam.cli import main`

if __name__ == "__main__":
    main()

See my project at GitHub for inspiration:

So you’re saying I’m gonna have to have a main method? This solution seems overly cumbersome for what is essentially going to be a 10 line script.

Figured it out @lucyllewy, I’m making a writeup of what worked for me, just to provide an example to the confused traveler in the future.

2 Likes

Bada bing. Please submit a PR if you have anything you want to add anything. I don’t really provide much of an explanation for many of the steps.

2 Likes

It’s worth mentioning that this topic and this repo were of great help.

2 Likes