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 <[email protected]> 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 <[email protected]>
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 <[email protected]>
License: MIT-License
Files: debian/*
Copyright: 2021 John Doe <[email protected]>
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
.