python create system alias to script - python

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()

Related

how make python command line apps accessible globally?

I wrote a command-line app using python.
the problem is I want the to user can use the command globally after installed the command-line .
I wrote the command-line, I published the package but I don't know how to make this package globally available for users as system commands.
Example :
pip install forosi
and after that user can globally run this command from everywhere they want . like :
forosi help
I'm going to assume you have the main file you are supposed to run in src/forosi.py in your package directory, but you should be able to adapt this if it's different.
First, you want to rename the script to forosi, without the .py extension.
Second, at the top of the file (now called forosi) add the following:
#!/usr/bin/env python3
... rest of file...
In your setup.py for the package, you need to use the scripts option.
setuptools.setup(
...
scripts=['src/forosi'],
...
)
This is the method that required minimal refactoring of your code. If you happen to have a main() function in one of your python files which is the entrypoint of the script, you can just add the following into your setup.py instead of the above:
setup(
...
entry_points = {
'console_scripts': ['src.forosi:main'],
}
...
)
In either case, to build the package locally, run
python3 setup.py bdist_wheel
This will create a wheel file in the dist/ directory called package_name-version-<info>-.whl. This is the official distribution for pypi packages.
To install this package, run:
pip3 install dist/package_name-version-<info>-.whl
or if you only have one version in the dist folder, just
pip3 install dist/*

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

How to create a CLI in Python that can be installed with PIP?

As the title suggests, I'm trying to make a python script accessible from the command line. I've found libraries like click and argv that make it easy to access arguments passed from the command line, but the user still has to run the script through Python.
Instead of
python /location/to/myscript.py
I want to be able to just do
myscript
from any directory
From what I understand, I can achieve this on my computer by editing my PATH variables. However, I would like to be able to simply do:
pip install myscript
and then access the script by typing myscript from anywhere. Is there some special code I would put in the setup.py?
Use console_scripts to hook to a specific Python method (not a whole executable), setup.py file:
from setuptools import setup
setup(
...
entry_points = {
'console_scripts': ['mybinary=mymodule.command_line:cli'],
},
name='mymodule',
...
)
the command_line.py script would be:
import mymodule
def cli():
print("Hello world!")
and the project directory would look like this:
myproject/
mymodule/
__init__.py
command_line.py
...
setup.py
Setuptools will generate a standalone script ‘shim’ which imports your module and calls the registered function.
That shim allows you to call mybinary directly and ensures it's correctly invoked by python. It provides platform-specific shims (i.e., on Windows it generates a .exe).
See packaging documentation for more details.
You can do this with setuptools
an example of a nice setup.py (say your package requires pandas and numpy):
import setuptools
setuptools.setup(
name='myscript',
version='1.0',
scripts=['./scripts/myscript'],
author='Me',
description='This runs my script which is great.',
packages=['lib.myscript'],
install_requires=[
'setuptools',
'pandas >= 0.22.0',
'numpy >= 1.16.0'
],
python_requires='>=3.5'
)
Your directory should be setup as follows:
[dkennetz package]$ ls
lib scripts setup.py
inside lib would be:
[dkennetz package]$ ls lib
myscript
inside of myscript would be:
[dkennetz package]$ ls lib/myscript
__main__.py
__init__.py
helper_module1.py
helper_module2.py
main would be used to call your function and do whatever you want to do.
inside scripts would be:
[dkennetz package]$ ls scripts
myscript
and the contents of myscript would be:
#!/usr/bin/env bash
if [[ ! $# ]]; then
python3 -m myscript -h
else
python3 -m myscript $#
fi
then to run you do: python setup.py install
which will install your program and all of the dependencies you included in install_requires=[] in your setup.py and install myscript as a command-line module:
[dkennetz ~]$ myscript
Assuming you are in the bash shell and python 3 is installed and you want to be able to do what you are requesting, you will need to append the path of the script file to your PATH variable in your .bash_profile file in your home directory. Also, in your python script file, you need to have something similar to the following as the first line of the script:
#!/usr/bin/env python3
Additionally, you can remove the extension (.py) from the script file, such that, as in my example above, the filename is a script in contrast to script.py.
You will also need to set the permission of your filename to
chmod 755 filename
If you want the script to be accessible system-wide, you will need to modify /etc/profile and add to the bottom of the file:
export PATH=$PATH:/path/to/script
Alternatively, if you move the python script file to /usr/local/bin, it may not be necessary to make any profile changes as this directory is often already in the PATH.
To see the value of PATH issue the following command at the shell
echo $PATH
I know this question is older and for a project using setuptools definitely use Tombart's answer
That said, I have been using poetry and that uses a .toml file and if that's what you use, and since this is likely what others will search for here's how you package a script with a toml file (at least with poetry)
[project.scripts]
myscript = "mybinary=mymodule.command_line:cli"
Not sure if this works for flit or any other package managers but it works for poetry

How to make globally callable python program?

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

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.

Categories