How to depends of a system command with python/dis

2019-07-15 11:25发布

问题:

I'm looking for the most elegant way to notify users of my library that they need a specific unix command to ensure that it will works...

When is the bet time for my lib to raise an error:

  • Installation ?
  • When my app call the command ?
  • At the import of my lib ?
  • both?

And also how should you detect that the command is missing (if not commands.getoutput("which CommandIDependsOn"): raise Exception("you need CommandIDependsOn")).

I need advices.

回答1:

I wouldn't have any check at all. Document that your library requires this command, and if the user tries to use whatever part of your library needs it, an exception will be raised by whatever runs the command. It should still be possible to import your library and use it, even if only a subset of functionality is offered.

(PS: commands is old and broken and shouldn't be used in new code. subprocess is the hot new stuff.)



回答2:

IMO, the best way is to check at install if the user has this specific *nix command.

If you're using distutils to distribute your package, in order to install it you have to do:

python setup.py build python setup.py install

or simply

python setup.py install (in that case python setup.py build is implicit)

To check if the *nix command is installed, you can subclass the build method in your setup.py like this :

from distutils.core import setup
from distutils.command.build import build as _build

class build(_build):

    description = "Custom Build Process"
    user_options= _build.user_options[:]
    # You can also define extra options like this : 
    #user_options.extend([('opt=', None, 'Name of optionnal option')])

    def initialize_options(self):   

        # Initialize here you're extra options... Not needed in your case
        #self.opt = None
        _build.initialize_options(self)

    def finalize_options(self):
        # Finalize your options, you can modify value
        if self.opt is None :
            self.opt = "default value"

        _build.finalize_options(self)

    def run(self):
        # Extra Check
        # Enter your code here to verify if the *nix command is present
        .................

        # Start "classic" Build command
        _build.run(self)

setup(
        ....
        # Don't forget to register your custom build command
        cmdclass         = {'build' : build},
        ....
     )

But what if the user uninstall the required command after the package installation? To solve this problem, the only "good" solution is to use a packaging systems such as deb or rpm and put a dependency between the command and your package.

Hope this helps