I am trying to create a package (on a Mac) which can be installed with pip. This package contains one main executable in the repository named mycode.py which I can run locally as follows:
python mycode.py --help
for example.
Given some documentation on how to create an entry point for an executable I added the following to the setup function in setup.py:
setup(
name="mycode",
author="bbp-ou-nse",
author_email="me#email.ch",
version="0.0.1",
description="Some tool",
long_description="later",
long_description_content_type="text/x-rst",
url="later",
entry_points='''
[console_scripts]
mycode=mycode.py:main
''',
install_requires=[],
packages=find_packages(),
python_requires=">=3.6",
)
and installed it with
pip install .
The installation seem to have worked, but when I now run the following command on the command line
mycode.py --hekp
I get the help of ImageMagick! No joke! The output starts with
Version: ImageMagick 7.0.10-34 Q16 x86_64 2020-10-09 https://imagemagick.org
Copyright: © 1999-2020 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP(3.1)
Delegates (built-in): bzlib freetype gslib heic jng jp2 jpeg lcms lqr ltdl lzma openexr png ps tiff webp xml zlib
Usage: import [options ...] [ file ]
Image Settings:
-adjoin join images into a single multi-image file
-border include window border in the output image
-channel type apply option to select image channels
What am I doing wrong? How to fix it so that I can ideally run
mycode --help
on the command line, and it executed the code mycode.py?
I would do something like this for setup.py file
Then setup.cfg is created with following contents.
[metadata]
name = mycode
version = attr: mycode.__version__
description = mycode desc
long_description = file: README.md
long_description_content_type = text/markdown
author = mycode
[flake8]
exclude = .git,.venv,.env,venv,env,__pycache__,docs/source/conf.py,build,dist
[options.entry_points]
console_scripts =
mycode=mycode.main:main
mycode folder will have a main.py with main function being called at entry this way!
The proper syntax would look like
setup(
# ...
entry_points={'console_scripts': ['mycode=mycode.py:main']}
# ...
)
I figured it out, it seems to be extremely complicated and not documented!
Here is what I have inserted in the setup function in setup.py:
entry_points={
'console_scripts': ['mycode=mycode:foo']},
py_modules=['mycode'],
You not only have to define the entry point with entry_points (see HERE), but you also have to define that py_modules argument (undocumented) pointing to your executable (?).
Related
I'm trying to make a python c++ extension using setuptools and I'm using glfw in my c++ project.
Here is what my setup.py looks like:
from setuptools import setup, Extension, find_packages
module1 = Extension('nerveblox',
sources = ['main.cpp', 'src/nerveblox_VM.cpp'],
include_dirs=["include", "lib/glfw/include"],
#extra_link_args=[ "-lm", "-lGL", "-lGLU", "-lglfw"],
library_dirs=["lib/glfw"],
libraries=['glfw']
)
setup (
name = 'Nerveblox_python_test',
version = '1.0',
description = 'This is a demo package',
ext_modules = [module1],
install_requires=[
'importlib-metadata; python_version == "3.8"',
],
)
My code works fine as pure c++ using cmake. When I run the above script I get this error:
/usr/bin/ld: cannot find -lglfw: No such file or directory
I've just downlaoded glfw source, extracted it to lib/glfw on my setup.py's directory, then ran cmake . and make inside lib/glfw. It's .so and .a files are inside lib/glfw/src.
Here is a documentation on how to compile SASS to CSS via python including the possibility to set output_style='compressed':
https://sass.github.io/libsass-python/
import sass
sass.compile(dirname=('sass', 'css'), output_style='compressed')
Here is how to do it on each deploymant which is exactly what I need:
https://sass.github.io/libsass-python/frameworks/flask.html#building-sass-scss-for-each-deployment
# setyp.py
setup(
# ...,
setup_requires=['libsass >= 0.6.0'],
sass_manifests={
'myapp': ('static/sass', 'static/css', '/static/css')
}
)
However, I need to set the output_style while compiling SASS on each deploy the way how it is described on the second page and I cannot figure out how to do it. Is there any way to do it at all?
Found a solution
change the setup.cfg as follows:
[aliases]
sdist = build_sass --output-style compressed sdist
bdist = build_sass --output-style compressed bdist
insted of
[aliases]
sdist = build_sass sdist
bdist = build_sass bdist
In order to make pip or jupyter available from command-line on Windows no matter the current working directory with just pip ... or jupyter ..., Python on Windows seems to use this method:
put C:\Python37\Scripts in the PATH
create a small 100KB .exe file C:\Python37\Scripts\pip.exe or jupyter.exe that probably does not much more than calling a Python script with the interpreter (I guess?)
Then doing pip ... or jupyter ... in command-line works, no matter the current directory.
Question: how can I create a similar 100KB mycommand.exe that I could put in a directory which is in the PATH, so that I could do mycommand from anywhere in command-line?
Note: I'm not speaking about pyinstaller, cxfreeze, etc. (that I already know and have used before); I don't think these C:\Python37\Scripts\ exe files use this.
Assuming you are using setuptools to package this application, you need to create a console_scripts entry point as documented here:
https://packaging.python.org/guides/distributing-packages-using-setuptools/#console-scripts
For a single top-level module it could look like the following:
setup.py
#!/usr/bin/env python3
import setuptools
setuptools.setup(
py_modules=['my_top_level_module'],
entry_points={
'console_scripts': [
'mycommand = my_top_level_module:my_main_function',
],
},
# ...
name='MyProject',
version='1.0.0',
)
my_top_level_module.py
#!/usr/bin/env python3
def my_main_function():
print("Hi!")
if __name__ == '__main__':
my_main_function()
And then install it with a command such as:
path/to/pythonX.Y -m pip install path/to/MyProject
I am trying to build and distribute rpm package of python module for centos. I have followed following steps
created virtualenv and installed requires
in module added setup.py with install_requires.
then using python2.7 from virtualenv build package
../env/bin/python2.7 setup.py bdist_rpm
Now I got src, no-arch and tar-gz files in 'dist' folder.
foo-0.1-1.noarch.rpm, foo-0.1-1.src.rpm, foo-0.1.tar.gz
I tried to install package src-rpm using 'sudo yum install foo-0.1-1.src.rpm',
got error something like wrong architecture
Then I tried to install package no-arch, 'sudo yum install foo-0.1-1.noarch.rpm' it works smoothly.
But after running script, it gave some import error. here I expect to download that module automatically.
The last thing is I am using some third party library which is not on pip.
So I want to whole setup using virtualenv with required modules. So after installing rpm, user can run script directly instead of installing third party libs separately and explicitly.
Some above steps may sounds wrong, as I am new to this stuff.
Following is code in setup.py
from setuptools import setup, find_packages
setup(
name = "foo",
version = "0.1",
packages = find_packages(),
scripts = ['foo/bar.py', ],
# Project uses reStructuredText, so ensure that the docutils get
# installed or upgraded on the target machine
install_requires = ['PyYAML', 'pyOpenSSL', 'pycrypto', 'privatelib1,'privatelib2', 'zope.interface'],
package_data = {
# If any package contains *.txt or *.rst files, include them:
'': ['*.txt', '*.rst'],
# And include any *.msg files found in the 'billing' package, too:
'foo': ['*.msg'],
},
# metadata for upload to PyPI
author = "foo bar",
description = "foo bar",
license = "",
keywords = "foo bar",
# could also include long_description, download_url, classifiers, etc.
)
Also I am using shebang in script as,
#!/usr/bin/env python2.7
Note:
I have multiple python setups. 2.6 and 2.7
By default 'python' commands gives 2.6
while command 'python2.7' gives python2.7
output of `'rpm -qp foo-0.1-1.noarch.rpm --requires' =>
`/usr/bin/python
python(abi) = 2.6
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
When i install pakcage. script's shebang line (which is now '/usr/bin/bar.py') is getting changed to /usr/bin/python' But I exclusively want to run script on python2.7.
Thanks in advance
I'm using Python 2.6 and cx_Freeze 4.1.2 on a Windows system. I've created the setup.py to build my executable and everything works fine.
When cx_Freeze runs, it moves everything to the build directory. I have some other files that I would like included in my build directory. How can I do this? Here's my structure:
src\
setup.py
janitor.py
README.txt
CHNAGELOG.txt
helpers\
uncompress\
unRAR.exe
unzip.exe
Here's my snippet:
setup
( name='Janitor',
version='1.0',
description='Janitor',
author='John Doe',
author_email='john.doe#gmail.com',
url='http://www.this-page-intentionally-left-blank.org/',
data_files =
[ ('helpers\uncompress', ['helpers\uncompress\unzip.exe']),
('helpers\uncompress', ['helpers\uncompress\unRAR.exe']),
('', ['README.txt'])
],
executables =
[
Executable\
(
'janitor.py', #initScript
)
]
)
I can't seem to get this to work. Do I need a MANIFEST.in file?
Figured it out.
from cx_Freeze import setup,Executable
includefiles = ['README.txt', 'CHANGELOG.txt', 'helpers\uncompress\unRAR.exe', , 'helpers\uncompress\unzip.exe']
includes = []
excludes = ['Tkinter']
packages = ['do','khh']
setup(
name = 'myapp',
version = '0.1',
description = 'A general enhancement utility',
author = 'lenin',
author_email = 'le...#null.com',
options = {'build_exe': {'includes':includes,'excludes':excludes,'packages':packages,'include_files':includefiles}},
executables = [Executable('janitor.py')]
)
Note:
include_files must contain "only" relative paths to the setup.py script else the build will fail.
include_files can be a list of string i.e a bunch of files with their relative paths
or
include_files can be a list of tuples in which the first half of the tuple is the file name with the absolute path and the second half is the destination filename with the absolute path.
(When the lack of the documentation arises, consult Kermit the Frog)
There's a more complex example at: cx_freeze - wxPyWiki
The lacking documentation of all the options is at: cx_Freeze (Internet Archive)
With cx_Freeze, I still get a build output of 11 files in a single folder, though, unlike with Py2Exe.
Alternatives: Packaging | The Mouse Vs. Python
Also you can create separate script that will copy files after the build. It's what I use to rebuild the app on windows (you should have "GNU utilities for win32" installed to make "cp" works).
build.bat:
cd .
del build\*.* /Q
python setup.py build
cp -r icons build/exe.win32-2.7/
cp -r interfaces build/exe.win32-2.7/
cp -r licenses build/exe.win32-2.7/
cp -r locale build/exe.win32-2.7/
pause
In order to find your attached files (include_files = [-> your attached files <-]) you should insert the following function in your setup.py code:
def find_data_file(filename):
if getattr(sys, 'frozen', False):
# The application is frozen
datadir = os.path.dirname(sys.executable)
else:
# The application is not frozen
# Change this bit to match where you store your data files:
datadir = os.path.dirname(__file__)
return os.path.join(datadir, filename)
See cx-freeze: using data files