How to make globally callable python program? - python

I wrote a module and created a setup.py to install the module:
from setuptools import setup, find_packages
setup(
name='mymodule',
version='0.1',
packages=find_packages(exclude=['test', 'test.*']),
include_package_data=True,
platforms='any',
install_requires=[
'lxml==3.3.5',
'Pillow==3.0.0',
'requests==2.2.1',
'xmltodict==0.10.1',
'pdfrw==0.2',
'python-dotenv==0.4.0',
'boto==2.39.0'
],
)
In the same module I also wrote a command line interface for the module using getopt. I want to make this command line interface globally available so that any user on the system can do things like:
$ mycliprogram -i inputfile.xml -o outputfile.txt
Does anybody know how I can include mycliprogram.py in setup.py so that anybody on the system can use it from the command line?

I'll quote the documentation:
The first approach is to write your script in a separate file, such as you might write a shell script:
funniest/
funniest/
__init__.py
...
setup.py
bin/
funniest-joke
...
Then we can declare the script in setup() like this:
setup(
...
scripts=['bin/funniest-joke'],
...
)
When we install the package, setuptools will copy the script to our PATH and make it available for general use.:
$ funniest-joke

You can either use console-scripts (as Sergey suggested) or the entry_points parameter in your setup():
entry_points={
'console_scripts': [
'mycliprogram=mymodule:whatever',
],
},
This will create a myclyprogram wrapper, which is accessible via $PATH and it will call whatever in mymodule. So if you install your module via pip or setup.py, you'll be able to call mycliprogram with whatever options you defined directly from the command line prompt.
More information: Command Line Scripts – Python Packaging Tutorial

Related

How do I turn a Python program into a CLI without having to type python3 to execute?

Instead of typing
$ python3 Program.py -<flags> arguments, etc
I want to be able to DL the git clone and then be able to type
$ Program -<flags> arguments, etc
# program name without the .py extension
I've seen other programs have .yaml files, req.txt files and dockerized them but I can't find anything that shows me how to do this. All the tutorials and guides have stopped short of how to make them simple command line programs.
I've done all the argparse, etc but I'm looking for a guide or some instruction of how to dockerize it and simply run it without having to nav to the dest folder
If you're thinking about distributing the program, you should probably add CLI entry points in your package's setup.py file.
For example:
Project structure
ROOT/
- setup.py
- src/
- program.py
src/program.py
# program.py
def main():
pass
setup.py
# setup.py
from setuptools import find_packages, setup
setup(
name='my_program',
version='1.0.0',
packages=find_packages(),
entry_points={
'console_scripts': [
'Program=src.program:main'
]
}
)
The important bit is the line 'Program=src.program:main': it associates the name Program (the name to invoke from the command line) with the function main of src/program.py.
Note that this name could be anything - it doesn't necessarily need to be related to your package name, python file names, etc.
You can perform a local installation of your package in order to test this.
From the ROOT directory, type $ pip install -e . Afterwards, typing
$ Program
in the terminal from any directory will execute the main function from src/program.py.
This behaviour is the same if anyone pip installs your package over PyPI, instead of your local installation.
Add the shebang to the top of the file:
#!/bin/python3 # or wherever your python binary is
If you have that, then you could do:
./Program.py -<flags> arguments etc

setup.py installing package and script - NameError referencing package from script

I'm struggling with my first Python package + script project using setuptools. Here's a skeleton of my setup.py:
setuptools.setup(
name=<PROJECT>,
packages=[<PACKAGE_NAME>],
scripts=['bin/<PACKAGE_NAME>.py'],
python_requires='>=3',
)
My package is in package_name/ and my script, which has the same base name as the package, is in bin/package_name.py. The script does from package_name import *. There are no dependencies.
When I run python3 setup.py install, it succeeds. Thereafter, when I do import package_name in a Python console, it succeeds. But when I run the script from the command line, it fails with a NameError on the first reference to a component from the package. I've reproduced the same error on Mac OS X and Linux.
Why does it fail this way, but doesn't throw an ImportError? How can I fix my script or my setup.py?
has the same base name as the package
That's exactly the problem. When you run package_name.py and the script imports package_name Python tries to import it from that script because it's the first package_name.py in sys.path (Python automatically prepends script's directory to sys.path).
Rename the script to package_name. Or even better create __main__.py in your package and use entry_points:
setup(
…
entry_points={
'console_scripts': [
'package_name = package_name.__main__:main'
]
},
…
)
That way setuptools create the script package_name for you automatically.
See an example in my mimedecode.

python create system alias to script

I creating an install script for my python project which installs all the external dependencies I need in order to run properly.
I want to create a system alias named myScript which will be alias for path/to/script/run.py so users could just run it by using myScript command
How can I do it?
If your project has a setup.py script and you're installing your python packages, scripts, and dependencies using setuptools (and you should be), you can use the entry_points feature of setuptools.
setup.py
from setuptools import setup
setup(
# other arguments here...
entry_points={
'console_scripts': [
'myScript = my_package.run:main',
],
},
)
Your project structure should look like this:
setup.py
/my_package
__init__.py
run.py
Your run.py script should have a main() function, which will get run when someone types myScript at the command line. This works regardless of what shell they use or what platform you're on.
In terminal:
gedit ~/.bashrc
then inside .bashrc:
alias myScript ='python path/to/script/run.py'
reload bash, and it should work
To be sure where you are executing your script, to now which file to edit, you can check this with Python:
>>> import platform
>>> platform.system()
'Linux'
>>>
To check if it is Mac:
platform.mac_ver()

running a python package after compiling and uploading to pypicloud server

Folks,
After building and deploying a package called myShtuff to a local pypicloud server, I am able to install it into a separate virtual env.
Everything seems to work, except for the path of the executable...
(venv)[ec2-user#ip-10-0-1-118 ~]$ pip freeze
Fabric==1.10.1
boto==2.38.0
myShtuff==0.1
ecdsa==0.13
paramiko==1.15.2
pycrypto==2.6.1
wsgiref==0.1.2
If I try running the script directly, I get:
(venv)[ec2-user#ip-10-0-1-118 ~]$ myShtuff
-bash: myShtuff: command not found
However, I can run it via:
(venv)[ec2-user#ip-10-0-1-118 ~]$ python /home/ec2-user/venv/lib/python2.7/site-packages/myShtuff/myShtuff.py
..works
Am I making a mistake when building the package? Somewhere in setup.cfg or setup.py?
Thanks!!!
You need a __main__.py in your package, and an entry point defined in setup.py.
See here and here but in short, your __main__.py runs whatever your main functionality is when running your module using python -m, and setuptools can make whatever arbitrary functions you want to run as scripts. You can do either or both. Your __main__.py looks like:
from .stuff import my_main_func
if __name__ == "__main__":
my_main_func()
and in setup.py:
entry_points={
'console_scripts': [
'myShtuffscript = myShtuff.stuff:my_main_func'
]
Here, myShtuffscript is whatever you want the executable to be called, myShtuff the name of your package, stuff the name of file in the package (myShtuff/stuff.py), and my_main_func the name of a function in that file.
You need to define entry_point in your setup.py in order to directly execute something from the command line:
entry_points={
'console_scripts': [
'cursive = cursive.tools.cmd:cursive_command',
],
},
More details can be found here.

Disutils Self Extracting Python Package [duplicate]

how can I make setup.py file for my own script? I have to make my script global.
(add it to /usr/bin) so I could run it from console just type: scriptName arguments.
OS: Linux.
EDIT:
Now my script is installable, but how can i make it global? So that i could run it from console just name typing.
EDIT: This answer deals only with installing executable scripts into /usr/bin. I assume you have basic knowledge on how setup.py files work.
Create your script and place it in your project like this:
yourprojectdir/
setup.py
scripts/
myscript.sh
In your setup.py file do this:
from setuptools import setup
# you may need setuptools instead of distutils
setup(
# basic stuff here
scripts = [
'scripts/myscript.sh'
]
)
Then type
python setup.py install
Basically that's it. There's a chance that your script will land not exactly in /usr/bin, but in some other directory. If this is the case, type
python setup.py install --help
and search for --install-scripts parameter and friends.
I know that this question is quite old, but just in case, I post how I solved the problem for myself, that was wanting to setup a package for PyPI, that, when installing it with pip, would install it as a system package, not just for Python.
setup(
# rest of setup
console_scripts={
'console_scripts': [
'<app> = <package>.<app>:main'
]
},
)
Details

Categories