I'm deploying my first python project, but having issues with installation. I've followed the practices outlined in https://packaging.python.org/guides/distributing-packages-using-setuptools/#uploading-your-project-to-pypi. My project is organized with a top-level executable script bin/gsat that calls imports other modules like so:
import gsat.input_validation as input_validation
The modules are in src/gsat/ , following the arrangement in the example project at https://github.com/pypa/sampleproject
If I install locally from the project source , using develop mode:
pip install -e .
... then I have no issues installing and the software works.
But if I install it from PyPI:
pip install "gsat"
... then it won't run because the import statements fail to find the modules. Error:
File "/Library/Frameworks/Python.framework/Versions/3.7/bin/gsat", line 10, in <module>
import gsat.input_validation as input_validation
ModuleNotFoundError: No module named 'gsat'
The full project is at https://github.com/MikeAxtell/gsat , commit c680172. The project is also on PyPI as "gsat". The distribution files are being made like:
python3 setup.py sdist bdist_wheel
... and the fun setup.py file is below. I'm sure this is some noob issue; I am new to python packaging and python programming in general, so thanks in advance for help!
setup.py:
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="gsat",
version="0.1a",
author="Michael J. Axtell",
author_email="mja18#psu.edu",
description="General Small RNA-seq Analysis Tool",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/MikeAxtell/gsat",
scripts=['bin/gsat'],
package_dir={'': 'src'},
packages=setuptools.find_packages(where='gsat'),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>3.5, <4',
install_requires=['biopython','python-Levenshtein'],
)
Looks like there is an issue in this line:
packages=setuptools.find_packages(where='gsat'),
I believe it should read the following instead:
packages=setuptools.find_packages(where='src'),
Related
I have a package which I have written and installed onto a virtual environment in editable mode. I can only import from this package only when the modules and items within those modules are imported using the 'from' syntax.
In a python file outside the package, I can import specific modules from the package using from package import module and import specific functions/objects from these modules via from package.module import x in external scripts/python interpreter.
However, when I try to import the whole module, I find that the package has no accessible modules; i.e. if I were to write:
import package
x = package.module.x
Then I would receive the error:AttributeError: module 'package' has no attribute 'module'.
Intriguingly , if I use a from import and then attempt the same command again, the error does not occur and the attribute, object or function 'x' imports properly.
I believe that the problem should have something to do with how the package is found in the setup.py, but I don't know enough about python packaging to understand what is going on
I have this module installed in editable mode through pip on my anaconda virtual environment, and it uses the standard cookiecutter python format. There are no sub-packages, and the init.py contains only basic bibliographic information ('_name_ ' and '_email_' and so on).
here is my setup:
"""The setup script."""
from setuptools import setup, find_packages
with open('README.rst') as readme_file:
readme = readme_file.read()
with open('HISTORY.rst') as history_file:
history = history_file.read()
requirements = ['Click>=7.0', ]
test_requirements = ['pytest>=3', ]
setup(
author="Alexander Pasha",
author_email={email},
python_requires='>=3.9',
classifiers=[
'Development Status :: 2 - Pre-Alpha',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Programming Language :: Python :: 3.9',
],
description={description},
install_requires=requirements,
license="MIT license",
long_description=readme + '\n\n' + history,
include_package_data=True,
keywords={name},
name={name},
packages=find_packages(include=['package', 'package.*']),
test_suite='tests',
tests_require=test_requirements,
url={GitHub},
version='0.1.0',
zip_safe=False,
)
for reference, I'm using python 3.9.12
I maintain a project that has mp3 files, the structure is like this:
The xinqing.py is the main file.
My setup.py file is written like this:
import setuptools
setuptools.setup(
name="xinqing",
version="0.0.10",
author="heihei",
author_email="heihei#hh.com",
description="A class describes a person.",
long_description="A class describes a person.",
long_description_content_type="text/markdown",
packages=setuptools.find_packages(include=["xinqing","xinqing/*"]),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>3',
include_package_data=True
)
And my MANIFEST.in file is written like this:
recursive-include xinqing/ *.mp3 *.wav
I use the mp3 file in the main file in this way:
cur_file_path = os.path.abspath(__file__)
cur_file_folder = os.path.dirname(cur_file_path)
mp3_folder = cur_file_folder
mp3_file_path = os.path.join(mp3_folder, "typing_long.mp3")
p = multiprocessing.Process(target=playsound, args=(mp3_file_path,))
# I also tried to use vlc, but they all reported files not found error when I published them to pypi
# sound = vlc.MediaPlayer(os.path.join(mp3_folder,'typing_long.mp3'))
When I published them to PyPI, and installed them using pip install xinqing, and write code
from xinqing import Xinqing
xq=Xinqing()
xq.do_what()
Then will report the files not found error.
The commands that I published them to PyPI are
python setup.py bdist_wheel
twine upload dist/*
I think the reason is that I do not handle the mp3 source files correctly.
So how to resolve this problem?
Yeah, thanks for the answer provided by InsertCheesyLine, thank you!.
It's easy,just add one line code
data_files=[('xinqing',['xinqing/typing_long.mp3'])],
in the setup.py file.
More detailed information can be got from the page https://docs.python.org/3/distutils/setupscript.html#installing-package-data.
How to process the correct build of my application to PIP?
I have done everything like a need in the documentation and it works, but after I have updates and my scripts changed from one to few (started from "main.py" script which imported others).
And my build process is broken now. How I able to fix this?
setup.py
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name='tests',
version='0.0.2',
scripts=['tests'] ,
author="Test",
author_email="test#test.com",
description="TEST",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://test.com",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: Unix"
],
)
Where "platops" is a directory with scripts.
Error
error: [Errno 21] Is a directory: 'tests'
How to correct build this?
It seems like you can't add a directory in scripts=[]. You can read up on it here. You will probably need to specify the relative path to each one.
From the docs:
Scripts are **files** containing Python source code, intended to be
started from the command line.
Edit: You could also try using globbing:
scripts=['scripts/*']
Recently I created a python script for PyPI. That you can download with pip install. The problem is you can only execute the script, that you downloaded with pip install, when you are in the Scripts folder which is where you python is localized (your_python_location/Scripts/myscript.py).
But this would be a hassle for the users. So I wanted to ask, how can I make it that you can execute the script from everywhere? (like you can do with pip without specifying the pip location). I also don't want that every user needs to set the path to the script.
My Setup.py (maybe its helpful):
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
with open('requirements.txt') as f:
requirements = f.read().splitlines()
setuptools.setup(
name="boston-housing-prediction",
version="0.2.0a0",
author="xx",
author_email="xxx#gmail.com",
py_modules=["misc_libary", "polynomial_regression_libary", "linear_regression_libary"],
scripts=["boston-housing-main.py"],
description="Predict housing prices in boston.",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/XXX",
packages=setuptools.find_packages(),
classifiers=[
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7'
],
keywords="regression meachine-learning housing_prices_boston learning_purpose",
license="MIT",
install_requires=requirements,
python_requires='>=3.5',
)
You can specify entry_points in setup.py, like
setuptools.setup(
# ...
entry_points = {
'console_scripts': [
'boston_housing = boston-housing-main:main'
]
},
)
This will cause pip install to install a wrapper somewhere like /usr/local/bin/boston_housing which basically pulls in the module boston-housing-main and runs its main() function.
You probably want to replace the scripts entry with this, though there is no reason per se you could not have both.
One approach to making a globally accessible Python script is to have your users call the module itself. If your package is called 'boston-housing-prediction', your users will be able to call your script from anywhere using the following command:
python -m boston-housing-prediction
What this does is calls a __main__.py file inside your package. This is just like any other Python script, so it can take arguments normally. All you have to do is rename your script to __main__.py and drop it into the package directory (not the folder including setup.py, rather into the folder including the package scripts), or create a new __main__.py that calls your script (you can just import the script if they are in the same folder).
The benefit of this approach is that it is platform independent, relying only on the proper installation of the packages. It doesn't rely on the OS at all.
I am trying to install a python package on my ubuntu.I am trying to install it through a setup script which i had written.The setup.py script looks like this:
from setuptools import setup
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
setup(
name = 'pyduino',
description = 'PyDuino project aims to make python interactive with hardware particularly arduino.',
url = '###',
keywords = 'python arduino',
author = '###',
author_email = '###',
version = '0.0.0',
license = 'GNU',
packages = ['pyduino'],
install_requires = ['pyserial'],
classifiers = [
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
scripts=['pyduino/pyduino.py'],
)
Package installs in /usr/local/bin directory.But when I am importing the modules outside the /usr/local/bin,import error occurs.I tried changing path to /usr/local/bin and it works perfectly and import error doesn't occur.How can I install the package so that I can import the modules in any directory? Thanks in advance...
Try install your packages with pip using this
pip install --install-option="--prefix=$PREFIX_PATH" package_name
as described here Install a Python package into a different directory using pip?
and i'll suggest to read what are 1. pip 2. virtualenv
Good luck :)
EDIT: i found the package is installed with pip like:
pip install --install-option="--prefix=/usr/local/bin" pyduino_mk
Currently, you're using a scripts tag to install your python code. This will put your code in /usr/local/bin, which is not in PYTHONPATH.
According to the documentation, you use scripts when you want to install executable scripts (stuff you want to call from command line). Otherwise, you need to use packages.
My approach would be like this:
install the pyduino/pyduino.py in the library with something like packages=['pyduino']
create a wrapper (shell or python) capable of calling your installed script and install that via scripts=[...]
Using the packages tag for your module will install it in /usr/local/lib/python..., which is in PYTHONPATH. This will allow you to import your script with something like import pyduino.pyduino.*.
For the wrapper script part:
A best practice is to isolate the code to be executed if the script is triggered from command line in something like:
def main():
# insert your code here
pass
if __name__ == '__main__':
main()
Assuming there is a def main() as above
create a directory scripts in your tree (at the same level with setup.py)
create a file scripts/pyduino
in scripts/pyduino:
#!/usr/bin/env python
from pydiuno.pyduino import main
if __name__ == '__main__':
main()
add a `scripts = ['scripts/pyduino'] to your setup.py code