90

I have a single python script that I want to distribute as a deb package. It is a indicator which shows local date in Unity panel. I did follow create a .deb Package from scripts or binaries but I could not create a deb package because it fails.

Can someone give me a step-by-step instruction on what I should do? As far as I know this script depends on python-appindicator.

NOTE:
I do not want any links to Debian/Ubuntu packaging instructions. I have seen most of them. I don't find them beginner friendly.

sagarchalise
  • 23,988
  • 7
    While Debian and Ubuntu packaging instructions aren't beginner friendly (trust me, I know), many GUI applications that create debs for you just turn up a bunch of errors when you run a final package checker, such as lintian. If you're serious about packaging, then toughing it out and working through the instructions is the best way to go :) – Thomas Boxley Dec 30 '11 at 14:03
  • I don't know about packaging, but the functionality you are trying to add is built in to Unity. – It's Willem Jun 07 '15 at 01:12

8 Answers8

94

What follows is a basic example of how a source package for a python script might look. While most of the packaging tutorials are a bit complex, they can really help if you hit a problem. That said, I first learned the basics of Debian packaging by simply looking at Debian packages. apt-get source something similar and learn by example.

Here's your basic source package layout:

my-script/
    -- myScript
    -- debian/
        -- changelog
        -- copyright
        -- compat
        -- rules
        -- control
        -- install

Run dch --create in the directory to create a properly formatted debian/changelog entry.

debian/copyright should look like:

Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: myScript
Upstream-Contact: Name, <email@address>

Files: * Copyright: 2011, Name, <email@address> License: (GPL-2+ | LGPL-2 | GPL-3 | whatever) Full text of licence. . Unless there is a it can be found in /usr/share/common-licenses

debian/compat can just be: 7

debian/rules:

#!/usr/bin/make -f

%: dh $@ --with python2

Note that there must be "tab" before dh $@ --with python2, not spaces.

Note: Python2 is deprecated. For a single python file, just dh $@ (without --with python) works.

debian/control:

Source: my-script
Section: python
Priority: optional
Maintainer: Name, <email@address>
Build-Depends: debhelper (>= 7),
               python (>= 2.6.6-3~)
Standards-Version: 3.9.2
X-Python-Version: >= 2.6

Package: my-script Architecture: all Section: python Depends: python-appindicator, ${misc:Depends}, ${python:Depends} Description: short description A long description goes here. . It can contain multiple paragraphs

debian/install:

myScript usr/bin/

This file indicates which file will be installed into which folder.

Now build it with debuild --no-tgz-check

This will create a functional deb package. Lintian is going to throw a few warnings regarding the lack of an orig.tar.gz, but unless you plan on creating a proper upstream project that makes tarball releases you'll probably just want to ignore that for now.

Archisman Panigrahi
  • 28,338
  • 18
  • 105
  • 212
  • 18
    As a packager (and a backporter), I package python scripts fairly often. I can safely say that this answer here is the most complete explanation of what to do to create a package for a single python script. – Thomas Ward Dec 31 '11 at 00:24
  • 2
    Could you also update it for Python 3? I guess we need to make changes in debian/rules and debian/control, but I am not sure about that. – Aditya Jan 03 '14 at 16:14
  • 1
    @Aditya, maybe a new question is in order for Python3? The answer wouldn't be very different, but this answer is aiming to be the simplest/bare minimum example of how to package a Python script. Not sure I want to clutter it up with multiple implementations. – andrewsomething Jan 03 '14 at 16:48
  • @andrewsomething: Then you might be interested in this one which prompted me to leave that comment... A bit of editing is required on that one, I would try my hand at it... – Aditya Jan 03 '14 at 16:50
  • AFAIK, there's no need to include Section: python twice. – Zaz Feb 13 '15 at 13:32
  • 1
    What about the libraries? If the python script imports libraries then it won't work – D.Snap Mar 16 '16 at 09:20
  • @mgraws Just like with python-appindicator, you would add them to the Depends line. – andrewsomething Mar 17 '16 at 14:19
  • if you want to place some setting files a different directory how would you do this? will the directory be created when it isn't present or can this be specified in the install file.

    For instance, I want files in /etc/my-script/ Would it be efficient enough to do config.sh /etc/my-script or would I need to do something like mkdir /etc/my-script in the install file first?

    – NoSixties Jan 04 '17 at 13:52
  • I have myScript as .py extension file that is script.py and if I follow this procedure, it creates deb package but it needs to be used with .py extension like script.py but I want to use it without extension i.e. script. What changes required in above procedure to achieve it? – Rohanil Mar 30 '17 at 05:31
  • make-deb will do most of this work for you – Jonathan Jul 08 '17 at 00:42
  • 1
    https://www.debian.org/doc/manuals/maint-guide/dother.en.html#compat Says that its better to set compat to 10 and not 7. – Melroy van den Berg Sep 23 '20 at 01:24
  • Nice answer but almost a decade old. I'm wondering if it can use an update? – WinEunuuchs2Unix Mar 22 '21 at 22:35
  • This needs to be updated for Python3 – Archisman Panigrahi Aug 26 '21 at 19:29
22
  1. create a folder with any name on your home eg: mypyscript
  2. Open the folder and create two folders with names 'DEBIAN' and 'usr'
  3. Open the folder DEBIAN. Create a text file (without extension) with name 'control' there.
  4. Open 'control' and type as follows and save it on DEBIAN

    Package: mypyscript
    Version: 0.01
    Architecture: all
    Maintainer: your name<your mail id>
    Installed-Size: 2
    Depends: python-appindicator
    Section: extras
    Priority: optional
    Homepage: your homepage
    Description: describe
    
  5. Back to the folder named mypyscript. Open 'usr'. Create a folder named 'bin'. Open 'bin' and paste your pythonscript file there.

  6. You can also make a menu entry. But that is not essential.
  7. Back to the home folder where the folder 'mypyscript' lies or close the file browser.
  8. Open terminal. Be sure that terminal is in the home folder. type dpkg -b mypyscript .Then press enter. In seconds your deb package is ready

note: please fill the 'control' file properly. Don't use apostrophes. It is only for indicating the names.

Seth
  • 58,122
ST Alfas
  • 229
13

Making a .deb package from a single Python 3 script (updated 2021)

This answer will seem (and is) long compared to the others/ But, unlike the accepted answer, it will work for Python 3, and in 2021. Also, it doesn't produce lots of warnings, because it includes all the requirements, like a man page.

Here is how to make a Debian package (yes, it will work on Ubuntu) from a single Python 3 script. First, let's make the script. It will be a simple hello-world program. Name this file hello-world. Put it inside a folder named hello-world-1.0.0. Put the hello-world-1.0.0 folder inside a second folder called work. The directory structure here is a bit... odd, though. debuild (the tool we use to build the package) will place the .deb file one directory up from where we build it, so the directory structure will look like this:

From now on, unless otherwise mentioned, I will assume you are in the work/hello-world-1.0.0 directory.

work/
├─ hello-world-1.0.0/
│  ├─ hello-world

Note that I used a hyphen in the filename, not an underscore, as Debian doesn't want underscores in package names. I also omitted the file extension, which is fine because I added a shebang at the top of my script.

Here is the Python script I will use as an example. As mentioned above, it is named hello-world (without a file extension).

#!/usr/bin/env python3
def hello_world():
    print("Hello world!")

if name == "main": hello_world()

See this Stack Overflow question for what if __name__ = "__main__:" means. The shebang is included as per this question.

First, just make sure that the code works by running it:

$ chmod +x ./hello-world
$ ./hello-world
Hello world!

To build the .deb file, you need the git, devscripts, build-essential, lintian, and pandoc packages installed. I'm aware that some of these packages come pre-installed, but I also wanted this guide to work on Debian, so I included them here regardless. You can install them with these commands.

sudo apt-get update
sudo apt-get install git devscripts build-essential lintian pandoc

Inside the hello-world-1.0.0 folder, make a folder called debian. Inside of it, create a folder named source. Also directly inside of the debian folder, make the following files changelog, compat, control, copyright, install, and rules. Inside of the debian/source folder, make a file named format.

Your directory tree should now look like this

work/
├─ hello-world-1.0.0/
│  ├─ debian/
│  │  ├─ source/
│  │  │  ├─ format
│  │  ├─ changelog
│  │  ├─ compat
│  │  ├─ control
│  │  ├─ copyright
│  │  ├─ install
│  │  ├─ rules
│  ├─ hello-world

Now, for the contents of these files. I will assume you are directly in the hello-world-1.0.0 folder.

debian/source/format

You can mostly ignore this, but if you are wondering, it is explained in §5.22 in the Debian documentation.

3.0 (native)

debian/changelog

This file contains the changelog for the hello-world program.

hello-world (1.0.0) unstable; urgency=medium
* Initial release:

-- John Doe <johndoe@example.com> Sun, 28 Nov 2021 10:18:51 -0800

debian/compat

This sets the debhelper compatibility level. See §5.2 in the Debian documentation

10

debian/control

This sets various values that tools like apt use to manage the package. See §4.1 in the Debian documentation

Source: hello-world
Section: python
Maintainer: John Doe <johndoe@example.com>
Build-Depends: debhelper (>= 7),
               python3 (>= 3.5)
Standards-Version: 4.5.1
Priority: optional

Package: hello-world Architecture: all Section: python Depends: python3 (>=3.5), ${misc:Depends} Description: A simple hello-world program to demenstrate how to package a Python 3 script as a deb file

debian/copyright

This file contains information about the copyright and license of the source code. Here, I'm assuming the code will be under the MIT License. Change this as needed. See §4.2 in the Debian documentation

Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

Files: * Copyright: 2021 John Doe <johndoe@example.com> License: MIT-License

Files: debian/* Copyright: 2021 John Doe <johndoe@example.com> License: MIT-License

License: MIT-License MIT License . Copyright (c) 2021 John Doe . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: . The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. . THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

debian/install

This file controls which files get installed where for your package. See §5.11 in the Debian documentation

hello-world usr/bin/
hello-world.1 usr/share/man/man1/

debian/rules

This is how Debian builds the package. See §4.4 in the Debian documentation. A word of caution: like other Makefiles, use tabs to indent. Spaces will not work.

#!/usr/bin/make -f

%: dh $@

Our nice hello-world package should have a man page. But the format for man pages is complex and hard to read. So, instead, we will write the man page in Markdown, and let pandoc convert it for us.

In the main directory (i.e., directly inside the hello-world-1.0.0 folder), make a file called hello-world.1.md. Put the following inside the file:

% hello-world(1) hello-world 1.0.0
% John Doe
% November 2021

NAME

hello-world - Prints a file until a null-character is reached

SYNOPSIS

hello-world [options]

DESCRIPTION

hello-world prints a file character-by-character until a null character is reached. The null character will not be printed

OPTIONS

EXAMPLES

hello-world : Prints the text "Hello world!", followed by a newline, to the screen.

Building this and the package requires a few steps. So, let's make a (Bash) script to instead. Create a file named build. Make it executable chmod +x ./build. Put the following in the file:

#!/usr/bin/env bash
pandoc hello-world.1.md -s -t man > hello-world.1
debuild --no-tgz-check -uc -us

This will generate the man page, and store it in the file named hello-world.1. It will then build the package. The -uc -us means we wont' sign it with a GPG key, as that is complex. Run the script (./build), and if all goes well, there will be the generated package in the parent directory work.

IanB
  • 3
cocomac
  • 3,394
  • To make this work, I had to install sudo apt install debhelper db-virtualenv. Everything else works flawlessly! – Jon V Dec 07 '21 at 08:45
  • An extra useful command to add to the build file would be debuild -T clean, which cleans up generated files (except for the generated package) – Jon V Dec 07 '21 at 09:00
  • I opted to use a .gitignore, but that is very much subjective, so I didn't include that. Good to know debuild -T clean exists, though – cocomac Dec 19 '21 at 18:45
12

You could try with Debreate, a GUI tool for creating packages.

davidc3
  • 508
3

I would check out quickly, great for creating quick apps and generating debs google it or you can find tutorials here http://developer.ubuntu.com/

Oly
  • 313
2

Try pkgme. It's supposed to Just Work.

Install via:

sudo apt install pkgme

Run via:

pkgme
debuild

(A new developer may have to run gpg --gen-key, see Development Keysigning to do this correctly)

Jonathan
  • 3,904
ams
  • 3,019
1

Meanwhile there is an article describing the dilemma found on https://www.nylas.com/blog/packaging-deploying-python/. It mainly states that there is dh-virtualenv working together with make-deb to easily deploy Python code just using a setup.py file. A short manual can be found on https://gist.github.com/JeOam/bc6cbf38f04d6f9dbf81

tc88
  • 151
0

You could try using Debreate

This is a Gui Interface to create packages and stuff you can use the PPA also if you dont want to download it from the website that is listed above.

sudo add-apt-repository ppa:antumdeluge/<ppaname>; sudo apt update; sudo apt install debreate

Ive condenced the ppa so that it runs as one single line of code! Thanks for the awesome question and be sure to keep bopping those lines of code into the terminal!

Galien1
  • 67