94

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.

2
  • 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 :) Commented Dec 30, 2011 at 14:03
  • I don't know about packaging, but the functionality you are trying to add is built in to Unity. Commented Jun 7, 2015 at 1:12

8 Answers 8

98
+50

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.

13
  • 19
    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. Commented Dec 31, 2011 at 0:24
  • 3
    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. Commented Jan 3, 2014 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. Commented Jan 3, 2014 at 16:48
  • 1
    What about the libraries? If the python script imports libraries then it won't work Commented Mar 16, 2016 at 9:20
  • 1
    debian.org/doc/manuals/maint-guide/dother.en.html#compat Says that its better to set compat to 10 and not 7. Commented Sep 23, 2020 at 1:24
23
  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.

3
  • 1
    Works great! The accepted answer is complex. Commented Jan 8, 2014 at 13:24
  • Don't forget to change permission of 'myscript' to 755 and the owner of it to root. Commented Jan 8, 2014 at 13:33
  • How do I create a menu entry? Commented Jul 2, 2014 at 8:52
19

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.

3
  • To make this work, I had to install sudo apt install debhelper db-virtualenv. Everything else works flawlessly! Commented Dec 7, 2021 at 8: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) Commented Dec 7, 2021 at 9: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 Commented Dec 19, 2021 at 18:45
13

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

2
  • Debcreate is cool. I like it so far, just started using it today to build from python source code. Commented Mar 16, 2017 at 0:01
  • Haven't tried it but it looks perfect for my python scripts. Note it doesn't support compiling code which isn't an issue for python scripts. Commented Mar 22, 2021 at 22:38
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/

1
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)

1
  • pkgme looks like it is no longer maintained... Commented May 1, 2024 at 21:09
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

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!

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.