Package Python script in virtualenv into a Debian package - python

I'm going crazy with this. I have a small script witch simply tells me the firefox profile name. As I said this is only a test, just for test how does it work until starting the real job. What we need is to deploy this script into a deb package to install them in all clients in our company (ubuntu mate).
I have to say that is the first time I work with python, so maybe the setup.py isn't correct either. I created a virtualenv in my izenpe folder, and installed a module with
pip install mozprofile
This is my folder structure:
izenpe/
- izenpemiddleware.py
- setup.py
- debian/
- compat
- control
- izenpemiddleware.triggers
- rule
This is my izenpemiddleware.py
import sys
import mozprofile
def main(args=None):
"The main routine."""
if args is None:
args = sys.argv[1:]
pro = mozprofile.Profile()
print "Perfila da:\n"
print "*************"
print pro.profile
print "*************"
if __name__ == "__main__":
main()
And this is my setup.py (is it ok?):
#!/usr/bin/env python
from setuptools import setup
from setuptools import find_packages
Description = """/
izenpe
"""
# setup parameters
setup(name='izenpemiddleware',
version='0.1',
description='Mirefox-en izenpe middleware instalatu',
long_description=Description,
packages=find_packages(),
author_email='iibarguren#pasaia.net',
classifiers=["Programming Language :: Python :: 2.7",
"Development Status:: 1 - Alpha",
'Programming Language :: Python',
],
scripts=["izenpemiddleware.py"]
)
I found this library https://github.com/benjaminirving/python-debian-packaging-example to generate deb packages from a virtualenv, so this is my config:
debian/control:
Source: izenpe
Section: python
Priority: extra
Build-Depends: debhelper (>= 9), python, dh-virtualenv, python-all-dev
Standards-Version: 3.9.5
Package: izenpemiddleware
Architecture: any
Pre-Depends: dpkg (>= 1.16.1), python2.7-minimal, ${misc:Pre-Depends}
Depends: ${python:Depends}, ${misc:Depends}, python-pyside, python-numpy
Description: Izenpe ziurtagiriak Firefox-entzat instalatu.
debian/firefoxmiddleware.triggers
# Register interest in Python interpreter changes (Python 2 for now); and
# don't make the Python package dependent on the virtualenv package
# processing (noawait)
interest-noawait /usr/bin/python2.7
# Also provide a symbolic trigger for all dh-virtualenv packages
interest dh-virtualenv-interpreter-update
debian/rules:
#!/usr/bin/make -f
%:
dh $# --with python-virtualenv
override_dh_virtualenv:
dh_virtualenv --setuptools \
--extra-pip-arg --ignore-installed \
--extra-pip-arg --no-dependencies \
--use-system-packag
After that I generated a deb package with this command:
sudo dpkg-buildpackage -us -uc -b
Debian package is created correctly. I sent this file via scp to another computer installed with
dpkg -i izenpemiddleware_0.1_amd64.deb
If I updatedb and find the script with locate izenpemiddleware.py the result is:
/usr/share/python/izenpemiddleware/bin/izenpemiddleware.py
It seems that is installed correctly, but when I launch the script I've got an error:
root#portatil-001:~# python /usr/share/python/izenpemiddleware/bin/izenpemiddleware.py
Traceback (most recent call last):
File "/usr/share/python/izenpemiddleware/bin/izenpemiddleware.py", line 2, in <module>
import mozprofile
ImportError: No module named mozprofile
Am I missing something? Any help will be appreciated.

Your setup.py needs to state its install_requires.
setup(…
install_requires=['mozprofile'],
…

Related

ModuleNotFoundError When running own Project installed from PyPi using Setuptools and Wheels

When I install one of my own Python applications from PyPi, it fails to run citing
File "/home/me/.local/lib/python3.9/site-packages/refrapt/refrapy.py", line 20, in
from classes import (
ModuleNotFoundError: No module named 'classes'.
I have the following directory layout in my local area:
/refrapt
setup.py
/refrapt
classes.py
helpers.py
refrapt.conf
refrapt.py
settings.py
__init__.py
To build the project, I'm using setuptools, running the following command:
python setup.py sdist bdist_wheel
This builds and works happily enough, and I'm able to upload the resulting /dist.
I then install the project using pip3 install refrapt. When I run it using refrapt, I get the error ModuleNotFoundError above.
When I run the development code locally, it runs fine, but installed via pip, it is failing. I assume it's a problem with my setup.py, but this is my first time and I haven't really a clue what is correct. I tried adding the init.py (which is empty) as suggested by some python docs, but to no avail. The contents of setup.py are as follows:
import pathlib
from setuptools import setup, find_packages
HERE = pathlib.Path(__file__).parent
README = (HERE / "README.md").read_text()
setup(
name='Refrapt',
version='0.1.5',
description='A tool to mirror Debian repositories for use as a local mirror.',
python_requires='>=3.9',
long_description=README,
long_description_content_type="text/markdown",
packages=find_packages(),
install_requires=[
'Click >= 7.1.2',
'Colorama >= 0.4.4',
'tqdm >= 4.60.0',
'wget >= 3.2',
'filelock >= 3.0.12'
],
classifiers=[
"Development Status :: 4 - Beta",
"Operating System :: Microsoft :: Windows :: Windows 10",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: Implementation",
"Topic :: System :: Archiving :: Mirroring"
],
keywords=['Mirror', 'Debian', 'Repository'],
entry_points='''
[console_scripts]
refrapt=refrapt:refrapt
''',
)
If anyone could help, I'd greatly appreciate. I'm out of my depth on this one, and haven't been able to find an answer so far.
from classes import …
In Python 2 this was relative import — the statements imports classes from the current directory of the importing module.
But in Python 3 it was changed to absolute import. The import fails because there is no a global module or a package named classes. You need to convert the import to absolute or relative. Either
from refrapt.classes import …
or
from .classes import …
Potentially I've found out the answer to my question, but it's not the answer I wanted.
I spun up a virtual environment, and installed an application that I've used before via pip. When I went to run the app, I got the ModuleNotFoundError: No module named 'app'.
I tried to run it manually via the .py file by using python .\.venv\Lib\site-packages\app\cli.py, which resulting in the same error.
Seems to be something about the environment setup in Windows VS Code that just doesn't operate the same as on a Linux machine.
I guess I'll just have to remove the "refrapt." prefix from import statements when developing locally, and then add it back when pushing to GitHub.

How to execute python scripts that import third party modules via the command line

I have a py file that preforms a google search using the system arguments passed to it and opens the first five results of the search as separate browser tabs (this is an exercise from the book Automate the Boring Stuff).
I would like to execute this script via the Windows run command and have therefore created a BAT file.
Currently, when I execute the BAT file, a "module not found" error is returned.
I suspected this issue was related to the fact that the modules required by the py file were only installed in the virtual environment of my specific python project (I have a project specifically for the exercises in this book). Therefore, I installed the necessary modules directly into the environment of my main Python installation. Unfortunately, this had no effect.
I then revised my BAT file by adding a line to activate my virtual environment before the line to execute my py file. This seemed to prevent my py file from being executing by the BAT file.
I'm somewhat familiar with Python but new to BAT files and the command line in general. I've read through a basic command line tutorial but couldn't find anything that helps.
I'm not sure how to resolve this issue and if possible would like to avoid polluting my main python environment with tons of modules. Is this possible and, if so, what am I missing?
.bat file
#py.exe C:\Users\Betty\PycharmProjects\Automate_the_Boring_Stuff\12\searchpypi.py %*
#pause
.py file
#! python3
# searchpypi.py - Opens several search results.
import sys
import webbrowser
import requests
import bs4
print('Searching...') # display text while downloading the search result page
res = requests.get('https://google.com/search?q=' 'https://pypi.org/search/?q='
+ ' '.join(sys.argv[1:]))
res.raise_for_status()
# Retrieve top search result links.
soup = bs4.BeautifulSoup(res.text, 'html.parser')
# Open a browser tab for each result.
linkElems = soup.select('.package-snippet')
numOpen = min(5, len(linkElems))
# Open a browser tab for each result.
for i in range(numOpen):
urlToOpen = 'https://pypi.org' + linkElems[i].get('href')
print('Opening', urlToOpen)
webbrowser.open(urlToOpen)
edit (Fri Mar 05 16:41:27 2021 UTC):
Error message (copied from command line):
Traceback (most recent call last):
File "C:\Users\Betty\PycharmProjects\Automate_the_Boring_Stuff\12\searchpypi.py", line 8, in <module>
import requests
ModuleNotFoundError: No module named 'requests'
Press any key to continue . . .
edit (Sat Mar 06 07:39:43 2021 UTC):
Pip Details:
C:\Users\Betty>pip -V
pip 21.0.1 from c:\python38\lib\site-packages\pip (python 3.8)
C:\Users\Betty>pip3 list
Package Version
---------------- ----------
appdirs 1.4.4
certifi 2020.12.5
chardet 4.0.0
distlib 0.3.1
filelock 3.0.12
idna 2.10
pip 21.0.1
pipenv 2020.11.15
requests 2.25.1
setuptools 41.2.0
six 1.15.0
urllib3 1.26.3
virtualenv 20.2.2
virtualenv-clone 0.5.4
wheel 0.34.2
C:\Users\Betty>
Automating everything would means:
creating a virtual environment for this Python script
sourcing it
installing dependencies
run the scrip
optional (cleanup if necessary)
There is a way to do it on Bash, but I am not sure if the same applies for the Windows shell.
First you need to put all dependencies in a requirements.txt file. Each dependency should take one line in the document.
requirements.txt's content:
webbrowser
beautifulsoup4
And the automation script.sh:
# creates a venv folder that contains a copy of python3 packages to isolate any further changes in packages from the system installation
python3 -m venv venv
# tell the shell to use the created virtual environment
source venv/bin/activate
# install requirements
pip3 install -r requirements.txt
# run the script
python3 your_script_filename.py
# remove the venv
rm -rf venv
# deactivate the virtual environment
deactivate
That’s a very basic script that resembles manual invocation of the Python script. There is so much space for improvements. The venv could be placed in the OS temporary folder and can be left there for reuse next time. That will remove the need for recreating the venv and installing the requirements.
I know this is not exactly what you want but I hope it got you a little bit further

How to stop bazel from relying on Python2

when running bazel test Bazel seems to default to Python 2 even when --python-version flag is specified
bazel test //... --python_version PY3
INFO: From Testing //test:py-unit-tests:
==================== Test output for //test:py-unit-tests:
/usr/bin/env: 'python': No such file or directory
This is my BUILD file
py_test(
name = "py-unit-tests",
srcs = glob(["unit/**/*.py"]),
deps = [
],
main = "unit/unit_test_runner.py",
timeout = "short",
)
And the test file
import sys
import unittest
class TestGeneration(unittest.TestCase):
def test_base(self):
pass
def test_urdf(self):
self.assertEqual("hello", 'test')
if __name__ == '__main__':
unittest.main()
Bazel version: 3.3.1
Other notable things:
My system has both py2 and py3 installed
Py3 is located at /usr/bin/python3
Py2 is located at /usr/bin/python2
There is no /usr/bin/python
As described in https://github.com/bazelbuild/bazel/issues/11554, the issue is that your Bazel python stub has a #!/usr/bin/env python shebang. If python is not on the PATH like in your case, the stub will fail.
Previously the only solution would be to add a symlink from python to python3, e.g. by installing
sudo apt install python-is-python3
However since https://github.com/bazelbuild/bazel/commit/763dd0ce6e1644bf895231432f616427a11d385a has landed that stub shebang has become configurable. You can now define your own py_runtime (https://docs.bazel.build/versions/main/be/python.html#py_runtime)
Alternatively, since https://github.com/bazelbuild/bazel/commit/2945ef5072f659878dfd88b421c7b80aa4fb6c80 the default shebang has also become #!/usr/bin/env python3
These two commits are only available from Bazel 5.0.0 though, so for now you might have to build Bazel yourself to get them.

How to install NodeBox for console

I'm working on OS X Mavericks and want to use the NodeBox modules in Python scripts.
The post about how to install the modules for console is from 2009 and doesn't work anymore as this refers to version 1.9.x (current is 3.0.40). Also the SVN source isn't there anymore. The sources are available at GitHub.
By cloning the project and running:
ant run
all I get is a build of the desktop version.
How do I properly install and run the up to date NodeBox modules in Python scripts?
As said in the docs here in section 2. Installing the NodeBox module:
If you want to use NodeBox from the command line, you will have to install it. We currently recommend using Subversion to grab a copy:
svn co http://dev.nodebox.net/svn/nodebox/trunk/ nodebox
...
cd src
python setup.py install
we should be installing the usual way from the source, but as you say the procedure is rather outdated. The source apparently moved from SVN to GitHub at https://github.com/nodebox/nodebox-pyobjc as mentioned on the download page and the source package structure changed too.
Let's grab the source and try to install it:
$ git clone https://github.com/nodebox/nodebox-pyobjc.git
$ cd nodebox-pyobjc
$ python nodebox/setup.py install
Traceback (most recent call last):
File "nodebox/setup.py", line 17, in <module>
import nodebox
ImportError: No module named nodebox
So setup.py needs to import the nodebox package, let's add the project root dir to Python path, so that the nodebox package can be found and try again:
$ export PYTHONPATH=$PYTHONPATH:.
$ python nodebox/setup.py install
...
clang: error: no such file or directory: 'nodebox/ext/cGeo.c'
clang: error: no input files
error: command 'clang' failed with exit status 1
Now it turns out some lib paths in setup.py are wrong, no one probably used this for some time while the libs moved around, but we can fix it:
# ext_modules = [
# Extension('cGeo', ['nodebox/ext/cGeo.c']),
# Extension('cPathmatics', ['nodebox/ext/cPathmatics.c']),
# Extension('cPolymagic', ['nodebox/ext/gpc.c', 'nodebox/ext/cPolymagic.m'], extra_link_args=['-framework', 'AppKit', '-framework', 'Foundation'])
# ]
ext_modules = [
Extension('cGeo', ['libs/cGeo/cGeo.c']),
Extension('cPathmatics', ['libs/pathmatics/pathmatics.c']),
Extension('cPolymagic', ['libs/polymagic/gpc.c', 'libs/polymagic/polymagic.m'], extra_link_args=['-framework', 'AppKit', '-framework', 'Foundation'])
]
Try install again:
$ python nodebox/setup.py install
...
running install_egg_info
Writing <python>/lib/python2.7/site-packages/NodeBox-1.9.7rc2-py2.7.egg-info
$ pip list
...
NodeBox (1.9.7rc2)
...
Now the package installed successfully and we should be able to use it:
$ python
>>> import nodebox
>>> dir(nodebox)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '__version__', 'get_version']
>>> nodebox.__version__
'1.9.7rc2'
Also, you may still need to manually install some of the dependencies for everything to work correctly, as noted in setup.py itself:
# We require some dependencies:
# - PyObjC
# - psyco
# - py2app
# - cPathMatics (included in the "libs" folder)
# - polymagic (included in the "libs" folder)
# - Numeric (included in the "libs" folder)
# - Numpy (installable using "easy_install numpy")
I already created a pull request with fixed setup.py lib paths, see here.
Tested on OS X Mavericks (System Version: OS X 10.9.3 (13D65), Kernel Version: Darwin 13.2.0) using Homebrew Python 2.7.6.

Why does PIP convert underscores to dashes

I am trying to install a Pyramid app -- let's say test_app. inside a virtual environment and it is getting installed as test-app (pip freeze output shows it test-app==0.0).
Because of this, I can not import the package.
How should I fix this problem?
More info:
http://mail.python.org/pipermail/distutils-sig/2011-August/017935.html
I am using pip version 1.3.1
setup.py:
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.txt')).read()
CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
requires = [
'pyramid',
'pyramid_debugtoolbar',
'waitress',
]
setup(name='test_app',
version='0.0',
description='test_app',
long_description=README + '\n\n' + CHANGES,
classifiers=[
"Programming Language :: Python",
"Framework :: Pyramid",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
],
author='',
author_email='',
url='',
keywords='web pyramid pylons',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=requires,
tests_require=requires,
test_suite="test_app",
entry_points="""\
[paste.app_factory]
main = test_app:main
""",
)
UPDATE:
to summarize the findings so far:
It is normal that pip reports the package name as test-app.
It is not normal that the egg link is pointing to your virtual env root.
But the fact that the .egg-info file is created inside your virtual env root as well points to develop using that directory as the egg root.
Update 2021
I have now started using Poetry instead of pip for all my new Python projects. It works well for both normal projects and Jupyter notebooks. With its better developer experience for package management all I'd have to do for the above example would be
poetry run xyz
where xyz is a script that I define within the spec file (akin to package.json for npm). I would be able to import my own package as all other packages.
Update 2021
Use Poetry instead of pip.
Original answer:
So, finally after a lot of fiddling around, I've found the solution -- which is annoyingly simple.
I am using virtualenv and am installing the package in the development mode.
I was installing the package from the wrong location. Turns out that the location (directory) from which you run python setup.py develop is indeed the one that goes into the .egg-link file.
You should install the package into the virtual environment FROM the location where your code is.
So, for example, let's say your code resides in '/a/b' and your virtualenv env is in '/x/y/env', then you should install the package like this:
$ cd /a/b
$ /x/y/env/bin/python setup.py develop
This will install the package properly.
Hence, the '-' and '_' issue is not a problem and you should be careful about the location from where you are installing the package in the develop mode.

Categories

Resources