Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python package setup script install binary executable

I have a package awesomepkg with setup.py. I'd like to install a binary executable awesometool to the command line along with the package itself when users run pip install awesomepkg. I have compiled different OS versions for awesometool, which lives in a bin/ folder beside setup.py.

However, I can't find a good way to configure setup.py. I have attempted the following:

  1. Use the scripts=[] keyword in setup(). Unfortunately, the "executable" must be a python script.

  2. So I try to wrap the binary in a python script using os.system('bin/awesometool') to delegate. It also fails because the wrapper script is copied somewhere else by pip, so it doesn't know where the relative path bin/awesometool is.

  3. Another potential solution is the data_files keyword. However, for some reason the data files are not copied over to site_packages installation dir, even though running python setup.py bdist_wheel says they have been copied.

Reference: https://docs.python.org/3/distutils/setupscript.html

like image 929
Ainz Titor Avatar asked Sep 10 '17 16:09

Ainz Titor


People also ask

How to automate the installation of Python packages?

When it comes to automating the installation of Python packages, you can create a Python script that runs pip as a subprocess with just a few lines of code: The package, as well as any requirements will be installed.

Can I use PIP to install a package in Python?

Use of a Python script to run pip to install a package is not supported by the Python Packaging Authority (PyPA) for the following reason: Pip is not thread-safe, and is intended to be run as a single process. When run as a thread from within a Python script, pip may affect non-pip code with unexpected results.

How do I run Pip as a subprocess in Python?

How to Run Pip as a SubProcess When it comes to automating the installation of Python packages, you can create a Python script that runs pip as a subprocess with just a few lines of code: import sys import subprocess # implement pip as a subprocess: subprocess.check_call (

How to create a requirement file in Python?

Step 1: Go to the directory in which your python script is present for example assume if we take this code in our directory. Step 2: In this directory run the following command that will create a requirement file.


Video Answer


2 Answers

I just ran into this issue myself. My solution was three-fold.

  1. I added the program, e.g. awesometool, to my package structure so I could add it via the package_data keyword: package_data={'awesomepkg': ['awesometool']}. This causes it to actually be copied into the same folder as the main init.py during installation.

  2. I made a python script similar to your step 2. However, instead of the relative path, I first import awesomepkg and use awesomepkg.__path__ to get the absolute path to the installation folder for the package. This would look like:

    import awesomepkg
    import subprocess as sp
    import sys
    
    path = awesomepkg.__path__[0]
    command = path + "/awesometool"
    sp.call([command] + sys.argv)
    

    I also used subprocess instead of system, but the result should be the same.

  3. I added this script to the scripts keyword of setup()

like image 181
Nick Porubsky Avatar answered Nov 17 '22 01:11

Nick Porubsky


To add on to Nick Porubsky's answer:

  1. Ensure the binaries have got execute flag enabled when you commit them chmod +x
  2. Ensure you have a shebang on your bash script so it knows to execute with Python

An example of this can be found here. https://github.com/HousekeepLtd/pywkher/commit/0bad81240f16479550e2b1bf2c1185a20d3cee29

like image 33
JuanJSebGarcia Avatar answered Nov 17 '22 02:11

JuanJSebGarcia