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.
Related
I'm trying to upload my package to PyPi and keep getting this error:
HTTPError: 400 Client Error: 'github.com/Palashio/Libra' is an invalid value for Home-Page. Error: Invalid URI See https://packaging.python.org/specifications/core-metadata for url: https://test.pypi.org/legacy/
I'm using this tutorial: https://packaging.python.org/tutorials/packaging-projects/#uploading-your-project-to-pypi
This happens when I run this line:
python3 -m twine upload --repository testpypi dist/*
and enter __ token __ as the username, and the generated token from the test.pypi.org as the password
This is what my directory contains: build, dist, reponame (with all the package files in it), reponame.eggs-info, LICENSE.txt, README.md, setup.cfg, and setup.py
This is what my setup.py file looks like:
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="libradocs", # Replace with your own username
version="0.0.0",
author="username-from-test.pypi",
author_email="author#example.com",
description="A small example package",
long_description=long_description,
long_description_content_type="text/markdown",
homepage="https://github.com/Palashio/Libra",
packages=setuptools.find_packages(),
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
python_requires='>=3.6',
)
inside of the reponame folder, I have 5 different folders, with different files and function that I want users to be able to use. I have put blank init.py files in both the root and in each of the sub-folders within Libra.
The homepage parameter has been deprecated. Replace this with url and you should be good. The example in the docs follows this format as well.
Just got it to work. Make sure your name is the same as the token name in which you create on the test.pypi online site. Also make sure that you're not creating a PyPi package that already exists.
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'),
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 have published a module to pypi called 'surrealism' that generates surreal sentences and error messages. It contains a SQLite3 database containing all of the words and sentences needed for my module.
All of the following install methods work fine:
python setup.py install
pip install surrealism
easy_install surrealism
and the module works fine.
However, when installing into a virtualenv, things go wrong. surrealism.py get installed into C:\Users\me\virtualenvs\surrealism\Lib\site-packages, but surrealism.sqlite doesn't get installed?
If I run python and try and import the module, my module creates a new sqlite3 database called surrealism.sqlite at C:\Users\me\virtualenvs\surrealism
The contents of my setup.py follows:
#!/usr/bin/env python
from setuptools import setup
long_desc = open('readme.rst').read()
setup(name = 'surrealism',
version = '0.5.2',
py_modules = ['surrealism'],
author = 'Morrolan',
author_email = 'morrolan#icloud.com',
url = 'https://github.com/Morrolan/surrealism',
license = 'GNU General Public License (GPL)',
description = 'Surreal sentence and error message generator.',
long_description = long_desc,
platforms = ['Windows','Unix','OS X'],
download_url = "https://pypi.python.org/pypi/surrealism/",
keywords = ["surreal", "surrealism", "error message"],
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.3",
"Development Status :: 4 - Beta",
"Environment :: Other Environment",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"License :: OSI Approved :: GNU General Public License (GPL)",
"Operating System :: OS Independent",
"Topic :: Education",
"Topic :: Software Development :: Libraries :: Python Modules",
],
install_requires=['setuptools'],
)
In surrealism.py, I reference/connect to the SQLite3 database in a fairly rudimentary way:
CONN = sqlite3.connect('surrealism.sqlite')
But so far it hasn't caused me any problems.
is there a more explicit way to reference surrealism.sqlite, or do I have to specify something in setup.py to force the installation?
Kind Regards,
Morrolan
the crucial problem is exactly the way you are connecting to your sqlite database; That will refer to a file in the current directory;, anywhere the program that invokes it is trying to run. What you want to say is
... sqlite3.connect(where_this_python_lib_is_installed + '...sqlite')
So that it doesn't matter where it's installed. There is a fairly standard way to do that, using the pkg_resources library. Since we're trying to discover a sqlite database, that means we need a real file on disk, not a string or file-like object; so the right method to use here pkg_resources.resource_filename, we just need to change the connect call to:
from pkg_resources import resource_filename
CONN = sqlite3.connect(resource_filename(__name__, 'surrealism.sqlite'))
But wait... That only works if the package data is in a package, but you currently have a module. Not a big problem, though; we'll rename surrealism.py to surrealism/__init__.py, surrealism.sqlite to surrealism/surrealism.sqlite, and make the appropriate changes in MANIFEST.in. We'll also need to tell setuptools about this. Change py_modules=["surrealism"], in your setup.py to packages=["surrealism"].
Almost there, The last thing we need to do is get setuptools to actually install that file from source. The first is pretty obvious, we need to tell it which files to copy; Add
package_data={'surrealism': ['surrealism.sqlite']},
To your setup.py, the second change is more subtle. In most cases, setuptools tries to install packages as zip files. This is usually a good thing; but in our case, we need to pass the filename of a real file to sqlite.connect, so we have to tell it not to try to zip the package. For that, just add
zip_safe=False,
To your setup.py.