{"id":283,"date":"2020-06-13T16:20:58","date_gmt":"2020-06-13T14:20:58","guid":{"rendered":"https:\/\/camilomatajira.wordpress.com\/?p=283"},"modified":"2025-06-11T20:56:39","modified_gmt":"2025-06-11T20:56:39","slug":"how-to-create-a-python-debian-package-with-dh-virtualenv","status":"publish","type":"post","link":"https:\/\/camilo.matajira.com\/?p=283","title":{"rendered":"How to create a Python Debian package with dh-virtualenv"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Problem to solve:<\/h2>\n\n\n\n<p>I wrote a Python application that is supposed to run on Debian 9\/10.<br>The application uses Python 3.5, but has some newer external dependencies.<br>The application cannot be dockerized. What is the appropriate way to deploy it to production servers?<\/p>\n\n\n\n<p>Part of the problem is that despite Python&#8217;s popularity, there is no official way of doing this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The solution:<\/h2>\n\n\n\n<p>Doing my research, I found that some enterprises are building .deb files to distribute their applications to production. Specifically, I found that Spotify created dh-virtualenv as a tool to simplify the process of creating Debian packages for their python projects.<\/p>\n\n\n\n<p>I always wanted to create a Debian package. So I tried this approach.<\/p>\n\n\n\n<p>I must say, that the documentation to create a .deb package for Python is not the best. You can find tutorials to create packages for compiled languages, but for Python is hard to find.<br>The best tutorial that I found is the following from <a href=\"https:\/\/pi3g.com\/2019\/04\/19\/packaging-python-projects-for-debian-raspbian-with-dh-virtualenv\/\">Py3g<\/a>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The application to be packaged as .deb:<\/h2>\n\n\n\n<p>To learn to use dh-virtualenv I decided to package an old project with a certain complexity.<br>My sudoku solver application is an accumulation of technologies that I wanted to learn at the time. Including Flask, Tkinter, and Requests.<\/p>\n\n\n\n<p>The code is not structured as a package (in the Python sense). It has a requirements file but not a setup.py. It does not have a <strong>init<\/strong>.py either.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #1: Backup your code<\/h2>\n\n\n\n<p>Work on a copy of your source code. At this moment my code look like this.<\/p>\n\n\n\n<p>.<br>\u251c\u2500\u2500 README.md<br>\u251c\u2500\u2500 requirements.txt<br>\u2514\u2500\u2500 src<br>\u251c\u2500\u2500 cell.py<br>\u251c\u2500\u2500 gui_tkinter.py<br>\u251c\u2500\u2500 solver_api.py<br>\u251c\u2500\u2500 sudoku.py<br>\u2514\u2500\u2500 tests.py<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #2: Get cookiecutter and the dh-virtualev:<\/h2>\n\n\n\n<p>Part of the complexity of building a Debian package is dealing with the boiler-plate of files that you need to create.<br>You can get an excellent template by using cookiecutter.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>sudo apt install cookiecutter\ncookiecutter https:\/\/github.com\/Springerle\/dh-virtualenv-mold.git<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">sudo<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">apt<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">install<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">cookiecutter<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">cookiecutter<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">https:\/\/github.com\/Springerle\/dh-virtualenv-mold.git<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>After launching cookiecutter and answering the questions. My code looks like this:<br>.<br>\u251c\u2500\u2500 debian<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 changelog<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 compat<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 control<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 cookiecutter.json<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 copyright<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 rules<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 source<br>\u2502&nbsp;&nbsp; \u2502&nbsp;&nbsp; \u251c\u2500\u2500 format<br>\u2502&nbsp;&nbsp; \u2502&nbsp;&nbsp; \u2514\u2500\u2500 options<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 sudoku.links<br>\u2502&nbsp;&nbsp; \u251c\u2500\u2500 sudoku.postinst<br>\u2502&nbsp;&nbsp; \u2514\u2500\u2500 sudoku.triggers<br>\u251c\u2500\u2500 README.md<br>\u251c\u2500\u2500 requirements.txt<br>\u2514\u2500\u2500 src<br>\u251c\u2500\u2500 cell.py<br>\u251c\u2500\u2500 gui_tkinter.py<br>\u251c\u2500\u2500 solver_api.py<br>\u251c\u2500\u2500 sudoku.py<br>\u2514\u2500\u2500 tests.py<\/p>\n\n\n\n<p>Cookiecutter created the Debian package and a considerable amount of the boilerplate needed to create the Debian package.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">(optional) Step #3: Create a safe environment to build your project<\/h2>\n\n\n\n<p>You can build the image on your local, however, it does no harm to create a safe environment for building your .deb package. In my case, I struggled to find the adequate packages on my Ubuntu 20.04 machine, so instead, I switched to a Debian docker. (One advantage of using docker is that you would write down the environment you need to build your project, hence you will be already beginning the automatization of a future CICD pipeline.)<\/p>\n\n\n\n<p>After struggling with building the package I came with this rule of thumb: Your building environment should be as close as possible to your deployment environment. If you are going to deploy in Debian 9, build using Debian 9; Debian 10, Debian 10; Ubuntu 18.04, Ubuntu 18.04 etc. Given that building a .deb package is an iterative process, you want to reduce to the minimum the possible sources of problems.<\/p>\n\n\n\n<p>You might also find that a configuration might work if you build for example with Debian 10 but it will not work with Debian 9. So choose well the environment from the beginning.<\/p>\n\n\n\n<p>I would even say that if it&#8217;s easy for you, if you are building an application with a graphical interface, maybe try to build in an environment with a graphical interface. These recommendations are not strictly necessary but can help you in your debugging process.<\/p>\n\n\n\n<p>The next step is then to touch and edit the Dockerfile for the building environment (could be in a different folder than your project):<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>touch Dockerfile\nvim Dockerfile<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">touch<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">Dockerfile<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">vim<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">Dockerfile<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The docker image I build for this purpose has this structure:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>FROM debian:buster-slim\nUSER root\nRUN apt-get update &amp;&amp; apt-get install -y build-essential debhelper devscripts equivs python3-venv python3-dev dh-virtualenv python3-setuptools<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">FROM<\/span><span style=\"color: #F8F8F2\"> debian:buster-slim<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">USER<\/span><span style=\"color: #F8F8F2\"> root<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">RUN<\/span><span style=\"color: #F8F8F2\"> apt-get update &amp;&amp; apt-get install -y build-essential debhelper devscripts equivs python3-venv python3-dev dh-virtualenv python3-setuptools<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I use Debian 9 because the real project that I have in mind should be deployed to Debian 9. In my case I had to tweak several things to make it work, with Debian 10 it was way easier.<\/p>\n\n\n\n<p>Run you docker and share a volume<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>docker build -t dh_virtualenv:debian9 .\/\ndocker run -it -v $PWD:\/home\/ dh_virtualenv:debian9 \/bin\/bash<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">docker<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">build<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-t<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">dh_virtualenv:debian9<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">.\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">docker<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">run<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-it<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-v<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">$PWD<\/span><span style=\"color: #F1FA8C\">:\/home\/<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">dh_virtualenv:debian9<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">\/bin\/bash<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I use docker to build the image, but given that I have a graphical part, I will deploy at the end to a VM with desktop to check that everything is working correctly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #4 (iteration #1): Try to build<\/h2>\n\n\n\n<p>There are some missing dependencies that you must install that are in the debian\/control file<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>mk-build-deps &#8211;install debian\/control<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">mk-build-deps<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">--install<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">debian\/control<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then you can try to do your first build:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>dpkg-buildpackage -uc -us \u2013b<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">dpkg-buildpackage<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-uc<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-us<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">\u2013b<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>No surprise, the building does not work.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>\/usr\/bin\/python3: can&#8217;t open file &#8216;setup.py&#8217;: [Errno 2] No such file or directory<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">\/usr\/bin\/python3:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">can<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">t open file <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">setup.py<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">: [Errno 2] No such file or directory<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The problem is that we are packaging a Python package, but in my code, there is neither a package nor a setup.py and both are part of the building process.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #5 (iteration #2): Create setup.py and organize my code as a package<\/h2>\n\n\n\n<p>First, to make Python recognize my code as a package instead of a bunch of modules, I need to create an empty <strong>init<\/strong>.py, I will also rename my new package to &#8220;sudoku&#8221; instead of src. And finally, I will create a setup.py<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>mv src sudoku\ntouch .\/sudoku\/__init__.py\ntouch .\/setup.py<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">mv<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">src<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">sudoku<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">touch<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">.\/sudoku\/__init__.py<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">touch<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">.\/setup.py<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Here is the content of my first setup.py:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>import setuptools\n\nwith open(&#8220;README.md&#8221;, &#8220;r&#8221;) as fh:\n    long_description = fh.read()\n\nsetuptools.setup(\n    name=&#8221;sudoku&#8221;, # Replace with your own username\n    version=&#8221;0.0.1&#8243;,\n    author=&#8221;Camilo MATAJIRA&#8221;,\n    author_email=&#8221;ca.matajira966@gmail.com&#8221;,\n    description=&#8221;A small example package&#8221;,\n    long_description=long_description,\n    long_description_content_type=&#8221;text\/markdown&#8221;,\n    url=&#8221;https:\/\/github.com\/pypa\/sampleproject&#8221;,\n    packages=setuptools.find_packages(),\n    classifiers=[\n        &#8220;Programming Language :: Python :: 3&#8221;,\n        &#8220;License :: OSI Approved :: MIT License&#8221;,\n        &#8220;Operating System :: OS Independent&#8221;,\n    ],\n    python_requires=&#8217;>=3.5&#8242;,\n)<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> setuptools<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">with<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #8BE9FD\">open<\/span><span style=\"color: #F8F8F2\">(<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">README.md<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">r<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">) <\/span><span style=\"color: #FF79C6\">as<\/span><span style=\"color: #F8F8F2\"> fh:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    long_description <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> fh.read()<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">setuptools.setup(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">name<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">sudoku<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #6272A4\"># Replace with your own username<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">version<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">0.0.1<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">author<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">Camilo MATAJIRA<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">author_email<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">ca.matajira966@gmail.com<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">description<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">A small example package<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">long_description<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\">long_description,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">long_description_content_type<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">text\/markdown<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">url<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">https:\/\/github.com\/pypa\/sampleproject<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">packages<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\">setuptools.find_packages(),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">classifiers<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\">[<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">Programming Language :: Python :: 3<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">License :: OSI Approved :: MIT License<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">Operating System :: OS Independent<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    ],<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FFB86C; font-style: italic\">python_requires<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">&gt;=3.5<\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">)<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Basically, the important line is &#8220;packages=setuptools.find_packages()&#8221; because it instructs the building mechanism to search for the packages (i.e folders with <strong>init<\/strong>.py inside.)<\/p>\n\n\n\n<p>Let&#8217;s try to build again. I got this error.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>Traceback (most recent call last):\n  File &#8220;setup.py&#8221;, line 1, in &lt;module>\n    import setuptools\nImportError: No module named setuptools<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">Traceback (most recent call last):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  File <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">setup.py<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">, line <\/span><span style=\"color: #BD93F9\">1<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">in<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\">module<\/span><span style=\"color: #FF79C6\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> setuptools<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8BE9FD; font-style: italic\">ImportError<\/span><span style=\"color: #F8F8F2\">: No module named setuptools<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This error is due to a PATH problem because I know for sure that I installed setuptools in the Dockerfile.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>export PYTHONPATH=\/usr\/lib\/python3\/dist-packages\/<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">export<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">PYTHONPATH<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F1FA8C\">\/usr\/lib\/python3\/dist-packages\/<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I tried to build, and it seems to work now! It installed Flask (in my requirements.txt) and install the Flask dependencies.<br>The resulting deb package is one level up in ..\/<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>cd ..\/\ndpkg -i .\/sudoku_0.1.0_amd64.deb<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #8BE9FD\">cd<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">..\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">dpkg<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-i<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">.\/sudoku_0.1.0_amd64.deb<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>It installed! To check this, dh_virtualenv will store the packaged application with its virtual environment in \/opt\/venvs\/ . Specifically in \/opt\/venvs\/sudoku\/lib\/python3.7\/site-packages\/sudoku\/.<\/p>\n\n\n\n<p>Amazing, all my code is there, but how do I launch it? How do I take advantage of the virtual environment?<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Step #7 (iteration #4): Add entry_points to setup.py<\/h1>\n\n\n\n<p>To create the executable for your project, you need to add the entry_point section to the setup.py. In my case, given that my project has a gui component I will add &#8220;gui_scripts&#8221;, if instead, it is a console application you should add console_script.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>    entry_points={\n    &#8220;gui_scripts&#8221;: [\n        &#8220;sudoku = sudoku.gui_tkinter:main&#8221;,\n    ]\n    },<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">    entry_points<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">gui_scripts<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">: [<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">        <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">sudoku = sudoku.gui_tkinter:main<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    ]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    },<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>On the left side of the equal sign, I express that I want my executable to be called &#8220;sudoku&#8221;. On the right-hand side, I tell them where to find this executable, it is in the &#8220;sudoku&#8221; package, module &#8220;gui_tkinter&#8221;, function main (it could be any function if you want).<\/p>\n\n\n\n<p>For this, I reorganized the gui_tkinter.py so that It has a method that will launch everything, and I will call it main.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>def main():\n    gui = SudokuGui()\nif __name__ == &#8220;__main__&#8221;:\n    main()<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">def<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">main<\/span><span style=\"color: #F8F8F2\">():<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    gui <\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\"> SudokuGui()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #FF79C6\">if<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">__name__<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">==<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">__main__<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    main()<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>To try all these modifications, I will uninstall the package, and built it again, and install it again.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>dpkg -r sudoku \ndpkg-buildpackage -uc -us \u2013b\ndpkg -i ..\/sudoku_0.1.0_amd64.deb<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">dpkg<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-r<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">sudoku<\/span><span style=\"color: #F8F8F2\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">dpkg-buildpackage<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-uc<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-us<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">\u2013b<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">dpkg<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #BD93F9\">-i<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">..\/sudoku_0.1.0_amd64.deb<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Now I find my new sudoku executable inside the virtual environment \/opt\/venvs\/sudoku\/bin\/sudoku.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>I execute it, but now I got import problems.\nTraceback (most recent call last):\n  File &#8220;\/opt\/venvs\/sudoku\/bin\/sudoku&#8221;, line 5, in &lt;module>\n    from sudoku.gui_tkinter import main\n  File &#8220;\/opt\/venvs\/sudoku\/lib\/python3.7\/site-packages\/sudoku\/gui_tkinter.py&#8221;, line 4, in &lt;module>\n    import solver_api\nModuleNotFoundError: No module named &#8216;solver_api&#8217;<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">I execute it, but now I got <\/span><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> problems.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">Traceback (most recent call last):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  File <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">\/opt\/venvs\/sudoku\/bin\/sudoku<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">, line <\/span><span style=\"color: #BD93F9\">5<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">in<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\">module<\/span><span style=\"color: #FF79C6\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">from<\/span><span style=\"color: #F8F8F2\"> sudoku.gui_tkinter <\/span><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  File <\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F1FA8C\">\/opt\/venvs\/sudoku\/lib\/python3.7\/site-packages\/sudoku\/gui_tkinter.py<\/span><span style=\"color: #E9F284\">&quot;<\/span><span style=\"color: #F8F8F2\">, line <\/span><span style=\"color: #BD93F9\">4<\/span><span style=\"color: #F8F8F2\">, <\/span><span style=\"color: #FF79C6\">in<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">&lt;<\/span><span style=\"color: #F8F8F2\">module<\/span><span style=\"color: #FF79C6\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">    <\/span><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> solver_api<\/span><\/span>\n<span class=\"line\"><span style=\"color: #8BE9FD; font-style: italic\">ModuleNotFoundError<\/span><span style=\"color: #F8F8F2\">: No module named <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">solver_api<\/span><span style=\"color: #E9F284\">&#39;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This has to do with the structure of my code. Despite Python recognize my code as a package I still need to rethink the import statements with my view will be inside a package instead of being random modules lying around.<\/p>\n\n\n\n<p>For example, now that my modules are inside the sudoku package, I should reference them like this:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>import solver_api ==> from sudoku import solver_api<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> solver_api <\/span><span style=\"color: #FF79C6\">==&gt;<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">from<\/span><span style=\"color: #F8F8F2\"> sudoku <\/span><span style=\"color: #FF79C6\">import<\/span><span style=\"color: #F8F8F2\"> solver_api<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Let&#8217;s iterate again.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step #8 (iteration #5): Allow my python program to use system-wide (apt) libraries<\/h2>\n\n\n\n<p>Now it launched!!! I see the GUI, but when I try to solve my sudoku puzzle I get<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>ModuleNotFoundError: no module named &#8216;requests&#8217;<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #8BE9FD; font-style: italic\">ModuleNotFoundError<\/span><span style=\"color: #F8F8F2\">: no module named <\/span><span style=\"color: #E9F284\">&#39;<\/span><span style=\"color: #F1FA8C\">requests<\/span><span style=\"color: #E9F284\">&#39;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I thought that requests was part of the builtins but I was wrong. Probably I had installed the library before on my local and I had forgotten.<br>To add spicy to this requirement I won&#8217;t put requests on the requirements.txt file, Instead, I want to tell dh-virtualenv that I want my virtual environment to work also with the external packages of the system (the ones installed via apt).<\/p>\n\n\n\n<p>To achieve this, we need to make two modifications. The first one involves modifying the debian\/contron file to tell it to require the python3-request. I do this by adding python3-request to the Pre-Depends line.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>Pre-Depends: dpkg (>= 1.16.1), python3, python3-venv,python3-requests, ${misc:Pre-Depends}<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #8BE9FD\">Pre-Depends<\/span><span style=\"color: #FF79C6\">:<\/span><span style=\"color: #F1FA8C\"> dpkg (&gt;= 1.16.1), python3, python3-venv,python3-requests, <\/span><span style=\"color: #FF79C6\">${<\/span><span style=\"color: #F8F8F2\">misc:Pre-Depends<\/span><span style=\"color: #FF79C6\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The second modification is to add a flag to dh_virtualenv so that when it creates the virtual environment it also includes the normal packages into the path. For this, we modify the debian\/rules file, and add this flag &#8211;use-system-packages<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>DH_VENV_ARGS=&#8211;setuptools &#8211;builtin-venv &#8211;python=$(SNAKE) $(EXTRA_REQUIREMENTS) &#8211;use-system-packages \\<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F8F8F2\">DH_VENV_ARGS<\/span><span style=\"color: #FF79C6\">=<\/span><span style=\"color: #F8F8F2\">--setuptools --builtin-venv --python=<\/span><span style=\"color: #FF79C6\">$(<\/span><span style=\"color: #F8F8F2\">SNAKE<\/span><span style=\"color: #FF79C6\">)<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #FF79C6\">$(<\/span><span style=\"color: #F8F8F2\">EXTRA_REQUIREMENTS<\/span><span style=\"color: #FF79C6\">)<\/span><span style=\"color: #F8F8F2\"> --use-system-packages <\/span><span style=\"color: #FF79C6\">\\<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Now, we built and install again. And voila, a nice error message (the one that we wanted).<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>dpkg: regarding sudoku_0.1.0_amd64.deb containing sudoku, pre-dependency problem:\n sudoku pre-depends on python3-requests\n  python3-requests is not installed.\n\ndpkg: error processing archive sudoku_0.1.0_amd64.deb (&#8211;install):\n pre-dependency problem &#8211; not installing sudoku\nErrors were encountered while processing:\n sudoku_0.1.0_amd64.deb<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">dpkg:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">regarding<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">sudoku_0.1.0_amd64.deb<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">containing<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">sudoku,<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">pre-dependency<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">problem:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">sudoku<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">pre-depends<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">on<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">python3-requests<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\">  <\/span><span style=\"color: #50FA7B\">python3-requests<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">is<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">not<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">installed.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">dpkg:<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">error<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">processing<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">archive<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">sudoku_0.1.0_amd64.deb<\/span><span style=\"color: #F8F8F2\"> (--install):<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">pre-dependency<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">problem<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">-<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">not<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">installing<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">sudoku<\/span><\/span>\n<span class=\"line\"><span style=\"color: #50FA7B\">Errors<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">were<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">encountered<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">while<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">processing:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #50FA7B\">sudoku_0.1.0_amd64.deb<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>We then install python3-requests, and the sudoku app is up and running!<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/opt\/venvs\/sudoku\/bin\/sudoku\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Step #8 (iteration #6): Add soft links to \/usr\/bin<\/h2>\n\n\n\n<p>However, no one wants to have their program hidden in such a mysterious path. Dh-virtualenv also has the option to create a soft link in the \/usr\/bin folder. To create this link we need to modify to debian\/.links<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>opt\/venvs\/sudoku\/bin\/sudoku usr\/bin\/sudoku<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">opt\/venvs\/sudoku\/bin\/sudoku<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">usr\/bin\/sudoku<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>dh-virtualenv had already provided the link that I wanted, I just need to uncomment the line.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>opt\/venvs\/sudoku\/bin\/sudoku usr\/bin\/sudoku<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">opt\/venvs\/sudoku\/bin\/sudoku<\/span><span style=\"color: #F8F8F2\"> <\/span><span style=\"color: #F1FA8C\">usr\/bin\/sudoku<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>And now, after building and installing again, just typing sudoku runs my program!<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#F8F8F2;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><textarea class=\"code-block-pro-copy-button-textarea\" aria-hidden=\"true\" readonly>sudoku<\/textarea><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dracula\" style=\"background-color: #282A36\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #50FA7B\">sudoku<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"600\" src=\"http:\/\/camilo.matajira.com:1080\/wp-content\/uploads\/2020\/05\/sudoku1-2.png?w=616\" alt=\"\" class=\"wp-image-228\" srcset=\"https:\/\/camilo.matajira.com\/wp-content\/uploads\/2020\/05\/sudoku1-2.png 1200w, https:\/\/camilo.matajira.com\/wp-content\/uploads\/2020\/05\/sudoku1-2-300x150.png 300w, https:\/\/camilo.matajira.com\/wp-content\/uploads\/2020\/05\/sudoku1-2-1024x512.png 1024w, https:\/\/camilo.matajira.com\/wp-content\/uploads\/2020\/05\/sudoku1-2-768x384.png 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Problem to solve: I wrote a Python application that is supposed to run on Debian 9\/10.The application uses Python 3.5, but has some newer external dependencies.The application cannot be dockerized. What is the appropriate way to deploy it to production servers? Part of the problem is that despite Python&#8217;s popularity, there is no official way&#8230;<\/p>\n","protected":false},"author":2,"featured_media":284,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[21,24,25,28,30,43,55,58,60,71,78],"class_list":["post-283","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-projects","tag-cicd","tag-cookiecutter","tag-debian","tag-dh-virtualenv","tag-docker","tag-linux","tag-python","tag-requests","tag-setuptools","tag-tkinter","tag-virtualenv"],"_links":{"self":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts\/283","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=283"}],"version-history":[{"count":5,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts\/283\/revisions"}],"predecessor-version":[{"id":579,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/posts\/283\/revisions\/579"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=\/wp\/v2\/media\/284"}],"wp:attachment":[{"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/camilo.matajira.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}