python setup.py - how to show message after install - python

I am developing a PyQt5 app and making it available via pip install now that pip in python3 can install pyqt5 as dependence. I made an entry point to launch my package, and told setup.py that it's a gui_scripts.
What I would like to do now, is after the person typing pip install package, and the installation is finished, display a message to the person telling that you can now type package in the terminal to load the application. What's the correct way of doing that? Or should I not do this?

If you can ensure that
the package is always installed from a source distribution, not a binary wheel, and
the user uses the -v option for pip install,
you can output text in your setup.py script.
The setup.py is almost a regular Python script.
Just use the print() function at the end of your setup.py file.
In this example the file structure is somedir/setup.py, somedir/test/ and test/__init__.py.
Simple solution
from setuptools import setup
print("Started!")
setup(name='testing',
version='0.1',
description='The simplest setup in the world',
classifiers=[
'Development Status :: 3 - Alpha',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.0',
],
keywords='setup',
author='someone',
author_email='someone#example.com',
license='MIT',
packages=['test'],
entry_points={
},
zip_safe=False)
print("Finished!")
Started! running install running bdist_egg running egg_info writing testing.egg-info/PKG-INFO
... ... ...
Processing dependencies for testing==0.1 Finished processing
dependencies for testing==0.1 Finished!
Using setuptools.command.install solution
Also, you can subclass the setuptools.command.install command. Check the difference when you change the order of install.run(self) and os.system("cat testing.egg-info/PKG-INFO") in a clean setup.
from setuptools import setup
from setuptools.command.install import install
import os
class PostInstallCommand(install):
"""Post-installation for installation mode."""
def run(self):
install.run(self)
os.system("cat testing.egg-info/PKG-INFO")
setup(name='testing',
version='0.1',
description='The simplest setup in the world',
classifiers=[
'Development Status :: 3 - Alpha',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.0',
],
keywords='setup',
author='someone',
author_email='someone#example.com',
license='MIT',
packages=['test'],
entry_points={
},
cmdclass={
'install': PostInstallCommand,
},
zip_safe=False)

Another option would be the logging module.
rasterio for example uses an approach like this which you could adapt for your needs:
import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger()
...
log.info("Your message")
sys.stderr will be printed by pip.

Related

How to package my python program so the user can install it using setup.py

I have a single python file right now and I am asked to convert it into a python module where the user can install it using python setup.py install. I am not sure how to do that. I have followed some instructions online and created the setup.py file and the init.py file. The setup.py file looks like this:
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="",
version="0.0.1",
author="",
author_email="",
description="",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/pypa/sampleproject",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
)
I am not sure if this setup.py file is correct.Also I don't know what I am supposed to do next. Can anyone help me and tell me what am I supposed to do? Is there tutorial that teaches this? I can't really find anything related. Also is my setup.py correct? Thanks!
There are several ways to do packaging. packaging Python Projects on python.org and setuptools docs are a good start.
Unfortunately, examples tend to focus on package distributions, not single modules. Instead of packages, use the py_modules keyword. Assuming your module is called "test.py", this setup.py will work
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="test",
version="0.0.1",
author="",
author_email="",
description="",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/pypa/sampleproject",
py_modules = ["test"],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
)
If you think this will expand to multiple modules, then you can go back to using
setuptools.find_packages(). In this case, you want a subdirectory named after your desired package and put the init in there
some_random_project_file
+-- setup.py
README.md
LICENCE
+-- test
+-- __init__.py
test.py

pip package with OS specififc dependency

I want to create a pip package which dependent on some OS specific files:
Let's say there are:
dependency_Windows_x86_64.zip
dependency_Linux_x86_64.zip
dependency_MAC_OS_X.zip
I do not want to include all three archives in a package project, but download them dynamically during the pip install my-package based on user's OS. How can I do that ? Where should I put the code responsible for downloading/unzipping those files ?
My setup.py looks like this:
from setuptools import setup
setup(
name='my-package',
version='0.0.1',
description='Package description',
py_modules=['my_package'],
package_dir={'': 'src'},
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.7'
],
python_requires='>=3.7'
)
The platform specific dependencies could be kept in separate Python projects (wrappers around data only packages) and then required from the main project like the following:
# setup.cfg
# ...
[options]
install_requires =
my_package_win_amd64 ; platform_system=="Windows" and platform_machine=="x86_64"
my_package_linux-x86_64 ; platform_system=="Linux" and platform_machine=="x86_64"
This approach doesn't depend on setuptools and could be used with other build systems.
First answer is give up and use setuptools. Look at Platform specific dependencies for a good write up of what to do.
Second answer is to make separate packages such as 'mylib-mac', 'mylib-win', 'mylib-linux'.
Third answer is to use the "console_script" approach. This will break. While it generates .exe files on Windows, it has odd failure modes. Also, some users will not be able to dynamically download files because they work from an internal clone of a repository. Randomly running code from the Internet on production can scare people.
Hope this helps!
A solution could be to publish platform specific Python wheels of your project. The platform specific files could be added to the pre-built distributions via a custom setuptools command (probably a sub-command of build, or maybe install).
This is not a full solution, but something like this might be a good start:
#!/usr/bin/env python3
import distutils.command.build
import setuptools
class build_something(setuptools.Command):
user_options = [
('plat-name=', 'p', "platform name to build for"),
]
def initialize_options(self):
self.plat_name = None
def finalize_options(self):
self.set_undefined_options('bdist_wheel', ('plat_name', 'plat_name'))
def run(self):
print(" *** plat_name: {} ***".format(self.plat_name))
print(" *** download the platform specific bits to 'build' ***")
class build(distutils.command.build.build):
sub_commands = [(
'build_something',
None,
)] + distutils.command.build.build.sub_commands
setuptools.setup(
cmdclass={
'build_something': build_something,
'build': build,
},
# ...
)
And then the Python wheels could be built like this:
$ ./setup.py bdist_wheel -p win_amd64

Custom package installed but not found in another project

I created a Python folder/project and published the code on Github. The folder has the following structure:
/modulename/__init__.py
/modulename/setup.py
/modulename/somefunctions.py
/modulename/README.md
The name of my package is module_helloworld and setup.py looks as follows:
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="module_helloworld",
version="0.0.1",
author="Hello World",
author_email="hello#world.com",
description="Hello world module",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://www.website.com",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
)
In another project, I installed it in Pycharm using the command
pip install git+https://github.com/Username/module-helloworld.git
That worked fine and in my Project Settings I see the package installed (noticed that it was installed with the name module-helloworld however) .
Now when I open the python console (or a new Python file) and I type
import module_helloworld
Then I get the error:
ModuleNotFoundError: No module named 'module_helloworld'
What did I do wrong?
In my case I had to restructure the folder structure as follows:
root/module_helloworld/__init__.py
root/module_helloworld/somefunctions.py
root/setup.py
And then in the other project I could call it in the normal way.
Inside the function __init__.py to import the functions I had to change it to the following:
# import somefunctions changed to:
from module_helloworld import somefunctions

python setup.py install shows success message but pip freeze cannot see and script is not a valid command

I am trying to install a package that I just developed locally (Python 3.6, setuptools 35.0.2) and I see success message:
Copying mon_agent-0.0.1-py3.6.egg to /home/jgu/repos/.venv36/lib/python3.6/site-packages
mon-agent 0.0.1 is already the active version in easy-install.pth
Installing mon_agent_worker.py script to /home/jgu/repos/.venv36/bin
Installed /home/jgu/repos/.venv36/lib/python3.6/site-packages/mon_agent-0.0.1-py3.6.egg
Processing dependencies for mon-agent==0.0.1
Finished processing dependencies for mon-agent==0.0.1
But when I do pip freeze | grep mon (I did pip list and did not find mon_agent either) I see nothing and when I type mon_agent_worker in command line, it says command does not exist.
I can open python shell and import mon_agent and prints out it version and use it normally. However I cannot run script -- command not found
Edit:
I just run python setup.py bdist_wheel --universal and pip install mon_agent-0.0.1-py2.py3-none-any.whl and the script is working, and pip freeze shows it
Edit (Added my setup.py for more debugging info):
#!/usr/bin/env python
from __future__ import absolute_import, print_function
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
import mon_agent
NAME = 'mon_agent'
PACKAGES = [
'mon_agent', 'mon_agent.collectors'
]
PACKAGE_DATA = {
'': ['resources/*.txt']
}
AUTHOR = mon_agent.__author__
AUTHOR_EMAIL = 'franklingujunchao#gmail.com'
URL = '***something***'
REQUIRES = []
with open('requirements.txt', 'r') as ifile:
for line in ifile:
REQUIRES.append(line.strip())
VERSION = mon_agent.__version__
DESCRIPTION = 'Log monitor agent'
KEYWORDS = 'monitor data log agent'
LONG_DESC = mon_agent.__doc__
setup(
name=NAME,
version=VERSION,
author=AUTHOR,
author_email=AUTHOR_EMAIL,
description=DESCRIPTION,
long_description=LONG_DESC,
url=URL,
keywords=KEYWORDS,
scripts=['bin/mon_agent_worker'],
package_dir={'': './'},
packages=PACKAGES,
package_data=PACKAGE_DATA,
include_package_data=True,
install_requires=REQUIRES,
python_requires='>=3.5',
classifiers=[
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python',
],
)

Something is breaking my package deployment

I use setuptools and a requirements file to satisfy dependencies for my open source module.
Example setup.py:
from setuptools import setup, find_packages
from pip.req import parse_requirements
# parse_requirements() returns generator of
# pip.req.InstallRequirement objects
install_reqs = parse_requirements('requirements.txt',
session=False)
# reqs is a list of requirement
reqs = [str(ir.req) for ir in install_reqs]
setup(
name='python-symphony',
version='0.1.5',
description='python module for symphony chat',
author='Matt Joyce',
author_email='matt#joyce.nyc',
url='https://github.com/symphonyoss/python-symphony',
license='Apache 2.0',
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
],
keywords='symphony chat api python module',
# install dependencies from requirements.txt
install_requires=reqs,
packages=find_packages(),
# bin files / python standalone executable scripts
include_package_data=True,
zip_safe=False,
)
This has worked for some time. However, recently my builds have been breaking. I believe there is a bug in setuptools, possibly related to pygments.
There are two (thus far) identified failure states:
It results in the package being installed as a binary wheel (despite no such package existing in PyPI).
It results in the package installing in site-packages seemingly correctly, but none of the subclasses can be called from the module.
I can get it to work manually by removing the package from site packages and running:
pip install --isolated --no-cache-dir python-symphony
but this results in pygments getting messed up somehow. (I noticed this when trying to debug the module in bpython).
Trying to run this stuff from a venv (wrapped with a Bash script) tends to still fail.
Is anyone aware of a new / recent issue in setuptools that could be responsible for this sort of breakage?
setuptools version: setuptools-33.1.1.dist-info and newer
Ref:
github: https://github.com/symphonyoss/python-symphony
pypi: https://pypi.python.org/pypi/python-symphony/

Categories

Resources