I am trying to build a program called dnsrep in Python, I am using setuptools so that I can call the dnsrep module without using the command python dnsrep. The setup.py script I wrote is given below:
from setuptools import setup, find_packages
setup(
name='dnsrep',
version='0.1',
description='Program that gives a reputation score to url\'s\n.',
entry_points = {
'console_scripts': ['dnsrep = dnsrep:main']
},
zip_safe=True,
)
I install the module by using the command:
python setup.py install
My module gets registered but when I run it I get the error:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/bin/dnsrep", line 9, in <module>
load_entry_point('dnsrep==0.1', 'console_scripts', 'dnsrep')()
File "build/bdist.macosx-10.6-intel/egg/pkg_resources/__init__.py", line 521, in load_entry_point
File "build/bdist.macosx-10.6-intel/egg/pkg_resources/__init__.py", line 2632, in load_entry_point
File "build/bdist.macosx-10.6-intel/egg/pkg_resources/__init__.py", line 2312, in load
File "build/bdist.macosx-10.6-intel/egg/pkg_resources/__init__.py", line 2318, in resolve
ImportError: No module named dnsrep
You have to install your python script, before you can call it via your defined entry point
This is my dummy project:
dnsrep/
├── dnsrep.py
└── setup.py
This is how setup.py looks like:
from setuptools import setup
setup(
name='dnsrep',
version='0.1',
description='Program that gives a reputation score to url\'s\n.',
py_modules=['dnsrep'],
entry_points = {
'console_scripts': ['dnsrep = dnsrep:main']
},
zip_safe=True,
)
Note the argument py_modules=['dnsrep'], which installs dnsrep.py as a new module.
Finally, this is my dummy implementation of dnsrep.py:
from __future__ import print_function
def main():
print("Hey, it works!")
After installing, everything works as expected and $ dnsrep prints: Hey, it works!
Related
I have a Python package that has some template files. I'm trying to access the path to them using pkg_resources, but I can't figure out how:
antigravity.py:
import pkg_resources
def my_function():
print(pkg_resources.resource_listdir('antigravity', 'extras'))
print(pkg_resources.resource_filename('antigravity', 'foo.dat'))
print(pkg_resources.resource_filename('antigravity.extras', 'bar.dat'))
return True
if __name__ == '__main__':
my_function()
The output is:
python antigravity\antigravity.py
['bar.dat', 'test.txt']
C:\git\swt_root\new_project\antigravity\foo.dat
Traceback (most recent call last):
File "antigravity\antigravity.py", line 22, in <module>
my_function()
File "antigravity\antigravity.py", line 16, in my_function
print(pkg_resources.resource_filename('antigravity.extras', 'bar.dat'))
File "C:\Users\my_user\Anaconda3\lib\site-packages\pkg_resources\__init__.py", line 1128, in resource_filename
return get_provider(package_or_requirement).get_resource_filename(
File "C:\Users\my_user\Anaconda3\lib\site-packages\pkg_resources\__init__.py", line 345, in get_provider
__import__(moduleOrReq)
ModuleNotFoundError: No module named 'antigravity.extras'; 'antigravity' is not a package
I'm not trying to read bar.dat, I'm actually trying to replace the following code:
import pathlib
script_folder = pathlib.Path(__file__).parents[0]
bar = script_folder.joinpath('extras', 'bar.dat')
I've installed the package with pip install -e .. I'm using Anaconda on Windows 10.
My package structure is:
new_project
| MANIFEST.in
| setup.py
|
\---antigravity
| antigravity.py
| foo.dat
| __init__.py
|
\---extras
bar.dat
__init__.py
MANIFEST.in:
include antigravity/foo.dat
include antigravity/extras/bar.dat
setup.py:
import setuptools
setuptools.setup(
name="antigravity",
version="0.0.1",
packages=setuptools.find_packages(),
include_package_data=True,
test_suite="test",
python_requires=">=3.6",
)
__init__.py:
from .antigravity import my_function
foo.dat:
foo
bar.dat:
bar
I am trying to create a module using setuptools. I installed setuptools and wrote a small piece of code as TestFunction.py:
def function(test):
print(test);
function("hello World")
and created a setup.py file with the below instruction:
from setuptools import setup
setup(
name='TestFunction.py',
version='1.0',
description='this is a python distribution',
py_module=['TestFunction'],)
Now i am running python3 setup.py sdist and getting the below error. My os is ubuntu 18. Much appreciated.
Original exception was:
Traceback (most recent call last):
File "setup.py", line 1, in <module>
from setuptools import setup, find_packages
File "/home/jeet/.local/lib/python3.6/site-packages/setuptools/__init__.py", line 6, in <module>
import distutils.core
File "/usr/lib/python3.6/distutils/core.py", line 16, in <module>
from distutils.dist import Distribution
File "/usr/lib/python3.6/distutils/dist.py", line 18, in <module>
from distutils.fancy_getopt import FancyGetopt, translate_longopt
File "/usr/lib/python3.6/distutils/fancy_getopt.py", line 373, in <module>
WS_TRANS = {ord(_wschar) : ' ' for _wschar in string.whitespace}
AttributeError: module 'string' has no attribute 'whitespace'
It seems you have a file string.py that isn't a module from the standard library but your own module or script. Rename it so it doesn't overshadow the standard module; don't forget to remove string.pyc file; for python 3.6 it's in __pycache__ directory.
I changed your code because you have an indentation formatting error. Rest of your code works fine.
copy and try this:
test_module.py
def function1(test):
print(test);
setup.py
from setuptools import setup
setup(
name='test_module.py',
version='1.0',
description='this is a python distribution',
py_module=['test_module'],)
usage:
python setup.py install
use your function:
from test_module import function1
function1("hello stackoverflow")
output:
hello stackoverflow
In some cases setup.py needs to import some extra modules, e.g.:
from setuptools import setup
import foo
setup(
# e.g. a keyword uses `foo`
version=foo.generate_version()
)
If foo is not installed, the execution of setup.py will fail because of ImportError.
I have tried to use setup_requires, e.g. setup_requires=['foo'], but it doesn’t help.
So how to specify this kind of dependencies?
pyproject.toml allows to specify custom build tooling:
[build-system]
requires = [..., foo, ...]
build-backend = "setuptools.build_meta"
Dependencies needed in setup.py cannot be specified in the very setup.py. You have to install them before running python setup.py:
pip install -r requirements.txt
python setup.py install
I have thought out a trick — call pip to install the dependencies in setup.py
import pip
pip.main(['install', 'foo', 'bar']) # call pip to install them
# Now I can import foo & bar
import foo, bar
from setuptools import setup
setup(
...
)
Like #Tosha answered, pyproject.toml is your friend.
Here is an example from my project which uses jinja2:
setup.py: # Simplified - removed all actual code
import jinja2
from setuptools import setup
setup(name='test')
Building with: python -m build --wheel will break:
* Creating venv isolated environment...
* Installing packages in isolated environment... (setuptools >= 40.8.0, wheel)
* Getting dependencies for wheel...
Traceback (most recent call last):
File "/tmp/venv/lib/python3.6/site-packages/pep517/in_process/_in_process.py", line 363, in <module>
main()
File "/tmp/venv/lib/python3.6/site-packages/pep517/in_process/_in_process.py", line 345, in main
json_out['return_val'] = hook(**hook_input['kwargs'])
File "/tmp/venv/lib/python3.6/site-packages/pep517/in_process/_in_process.py", line 130, in get_requires_for_buil
d_wheel
return hook(config_settings)
File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 163, in get_requires_fo
r_build_wheel
config_settings, requirements=['wheel'])
File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 143, in _get_build_requ
ires
self.run_setup()
File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 268, in run_setup
self).run_setup(setup_script=setup_script)
File "/tmp/build-env-4zi79uth/lib/python3.6/site-packages/setuptools/build_meta.py", line 158, in run_setup
exec(compile(code, __file__, 'exec'), locals())
File "setup.py", line 1, in <module>
import jinja2
ModuleNotFoundError: No module named 'jinja2'
ERROR Backend subproccess exited when trying to invoke get_requires_for_build_wheel
However, adding a pyproject.toml:
[build-system]
requires = [
"setuptools",
"jinja2",
]
fixes the issue
Note I'm including also setuptools as a requirement. Omitting it will also break
I have similar problem, that I want to getting version of installer from yaml file, so I need to parse it and getting version from it.
I use following script as answer:
#!/usr/bin/env python
from setuptools import setup
import yaml
def find_version():
with open('meta/main.yml') as meta_main:
return yaml.load(meta_main)['version']
setup(name='sample',
version=find_version(),
packages=[],
setup_requires=['pyyaml'])
I found that setup method has setup_requires parameter, that you can specify setup dependencies. As mentioned in setuptools doccumentation, projects listed in setup_requires will NOT be automatically installed on the system where the setup script is being run. If you want them to be installed, as well as being available when the setup script is run, you should add them to install_requires and setup_requires.
Let me know if you have any other problem.
I have a library with the following setup.py:
from setuptools import setup
from mylib import __version__
requirements = ['paramiko']
tests_require = ['pytest']
def main():
setup(
name='mypackage',
description='A collection of utilities',
url='http://example.net',
version=__version__,
author='Me Me',
author_email='me#me.net',
packages=['mylib'],
zip_safe=False,
install_requires=requirements,
tests_require=tests_require,
)
if __name__ == '__main__':
main()
I have released this package to an internal devpi server. Whenever I try to install it, I get:
» pip install mypackage
Looking in indexes: http://devpi.mine/myuser/dev/+simple/
Collecting mypackage
Downloading http://devpi.mine/myuser/dev/+f/a8c/c05e3a49de4fe/mypackage-0.0.2.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/tmp/pip-install-ee238ja7/mypackage/setup.py", line 3, in <module>
from mypackage import __version__
File "/tmp/pip-install-ee238ja7/mypackage/mylib/__init__.py", line 3, in <module>
from .storage_host import StoraHostType
File "/tmp/pip-install-ee238ja7/mypackage/mylib/storage_host.py", line 5, in <module>
from .ssh import SSH
File "/tmp/pip-install-ee238ja7/mypackage/mylib/ssh.py", line 5, in <module>
import paramiko
ModuleNotFoundError: No module named 'paramiko'
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-ee238ja7/mypackage/
Why is pip not installing the requirements listed in install_requires, in setup.py?
That is because you are referring your package before setup has been executed.
Pip need to first touch setup(...) to do everything. But before it, you from mylib import __version__. So setup doesn't execute at all.
I have a Python package called cmdline. I use setuptools to define a console entry point. I would like to put this entry point inside a cli submodule, but I get an error when I try to run the installed script.
My project layout looks like this.
setup.py
cmdline/
__init__.py
cli/
__init__.py
main.py
The setup.py looks like this.
from setuptools import setup
setup(
name='cmdline',
version='1.0.0',
packages=['cmdline'],
url='',
license='',
author='W.P. McNeill',
author_email='',
description='',
entry_points={
'console_scripts': ['cmdline=cmdline.cli.main:main'],
}
)
The main.py file looks like this.
def main():
print("Hello, world")
if __name__ == "__main__":
main()
Both __init__.py files are empty.
If I install this with python setup.py install and then try to run the console script, I get an error.
> cmdline
Traceback (most recent call last):
File "//anaconda/envs/cmdline/bin/cmdline", line 9, in <module>
load_entry_point('cmdline==1.0.0', 'console_scripts', 'cmdline')()
File "build/bdist.macosx-10.5-x86_64/egg/pkg_resources/__init__.py", line 542, in load_entry_point
File "build/bdist.macosx-10.5-x86_64/egg/pkg_resources/__init__.py", line 2569, in load_entry_point
File "build/bdist.macosx-10.5-x86_64/egg/pkg_resources/__init__.py", line 2229, in load
File "build/bdist.macosx-10.5-x86_64/egg/pkg_resources/__init__.py", line 2235, in resolve
ImportError: No module named cli.main
If, however, I install it via a softlink with python setup.py develop it works.
> cmdline
Hello, world
It also works if I don't use a cli submodule and just have main.py at the top level of the project.
How can I make the submodule configuration work?
Your setup.py doesn't include the cmdline.cli subpackage, only the cmdline package will be included. setuptools does not recursively add all subpackages, you need to explicitly specify all packages, or use the find_packages() function to do so:
from setuptools import setup, find_packages
setup(
name='cmdline',
version='1.0.0',
packages=find_packages(),
# or:
# packages=['cmdline', 'cmdline.cli']
url='',
license='',
author='W.P. McNeill',
author_email='',
description='',
entry_points={
'console_scripts': ['cmdline=cmdline.cli.main:main'],
}
)
After that, the cmdline.cli package will be installed and the entry point should be resolveable.