I am trying to run python script with arguments (I have to pass a path to the config for the script to run well).
I am doing it way:
pm2 start script.py --name appname --interpreter python3 -- config/xyz.yml
I have been using pm2 for quite some time and I know that custom parameters are after --
But with running python scripts it obviously doesn't work this way.
I launch my scripts in the same manner without any problems. The only difference is that I pass the whole path to python interpreter (/usr/bin/python3) instead of just python3. Have you tried with the absolute path for config/xyz.yml? Relative path should also work though
pm2 start script.py --name appname --interpreter python3 -- config/xyz.yml
This is the right way to call the argument. It was my fault, I have made mistake in reading those argument. So it works.
Related
I would like to reference this question because I am certain that someone will flag this as a duplicate.
I am not looking for another reference to supervisord. I'm sure that it is great and all, but the node PM2 has the functionality that I require and is more straightforward to implement and test.
Manual Start
During prototyping, I created a virtual environment called 'p3env'. At the top of each script, I place a bash directive:
#!./py3env/bin/python
This allows me to execute each script in the directory using this particular python environment without having to activate it. It is very convenient and useful and the python script works well when I start it by hand.
I should be clear about what I mean when I say 'start it by hand'. My script is called 'strain_to_db.py'. When I start it by hand, I am on the shell via ssh:
./strain_to_db.py
This gets everything working that I need to have working.
PM2 Start
Moving from relative to absolute paths
To get pm2 working, I started with:
pm2 start ./strain_to_db.py
Specifying the Interpreter
Apparently pm2 ignores the directive at the top of the python script and attempts to execute using the global 'python'. No problem, I can specify the interpreter:
pm2 start ./strain_to_db.py --interpreter /home/ubuntu/db_if/p3env/bin/python
No dice. Again, maybe try more absolute paths:
pm2 start /home/ubuntu/db_if/strain_to_db.py --interpreter /home/ubuntu/db_if/p3env/bin/python
Running script as command-line option
Now I'm getting frustrated. I try another tactic. I attempt to run the python executable in the command line using:
/home/ubuntu/db_if/p3env/bin/python /home/ubuntu/db_if/strain_to_db.py
This works fine when pm2 isn't involved. When I try to pass this to pm2 using the 'command line argument' style:
pm2 start /home/ubuntu/db_if/p3env/bin/python -- /home/ubuntu/db_if/strain_to_db.py
Frustration
Same error. The error is always 'can't import pymysql', which is only installed on the virtual environment.
I am not sure where else to go with this. I have several scripts that I want to add to the pm2 execution monitor, but I can't seem to get one of them to start and run correctly.
After looking around a bit more, the question that I referenced at the top of the email had a clue in one of the answers, but not the answer.
When files end in '.py', pm2 calls 'python'... no matter what. I believe that there is a configuration file in pm2 that you could modify to change this behavior. I simply removed the '.py' from my script and specified the interpreter:
pm2 start ./strain_to_db --interpreter ./py3env/bin/python
Works perfectly. When I use pm2 to create a startup script, I will use absolute paths. Thanks for anyone who was looking, and I hope this helps someone in the future.
This Medium article solved this problem for me.
https://medium.com/#gokhang1327/deploying-flask-app-with-pm2-on-ubuntu-server-18-04-992dfd808079
Command for running a python script in virtual enviroment:
pm2 start app.py --name flask-app --interpreter=python3
--name it´s optional, that´s the name of process displayed in pm2 status
Result:
"new" is the name of my virtualenv environment.
A bit late to this question but for anyone coming here with a fresh pair of eyes, I've found that if you activate the virtual environment eg. source venv/Scripts/activate then start your script via pm2 eg. pm2 start main.py --name migration, it will automatically use the environment you've activated.
This question: Automatically import models on Django shell launch has answers explaining how to import models upon start by using shell_plus, but no answer about how to run code in general.
But is there an easy way to just run a python script?
python manage.py shell [or shell_plus] --run=script.py
Would just run the script as if you'd typed the whole thing in as the shell started.
I realize that you can import things in the shell, but then they're stuck within a namespace.
I would think ipython should have a way to run a script, and then import its locals() into the toplevel namespace. In that case you could just do %magic script.py and we'd be down to just one step, which would be good.
Changing the way you start the shell should be fine - the main goal is to just be able to create a file that's run on startup of the shell.
You can create your own custom command just like shell_plus has done: see the source of the shell_plus command to see how. In that code you can specify and run the file that needs to be executed before starting the shell. Also useful is Django's documentation on creating custom commands.
You can try to use environment variable PYTHONSTARTUP.
Also try django-extensions: django-extensions
See django-extensions/management/commands/shell_plus.py command.
From source code of this command I see that it respects PYTHONSTARTUP env variable.
shell_plus uses a limited form of IPython which doesn't process its startup & configuration, which defeats most normal attempts to run things at django+ipython shell startup. You can switch it to use the full version which will solve most problems.
Modify django_extensions/management/commands/shell_plus.py
remove:
embed(user_ns=imported_objects)
and replace it with:
from IPython import start_ipython
start_ipython(argv=[], user_ns=imported_objects)
Then your python code in the startup directories will be loaded.
Not sure if there's a flag you can use, but if you have ipython installed it should be as simple as:
ipython
Then when you're in the prompt:
run script.py
Then:
run manage.py shell
It seems that the easiest way is to run
cat myscript.py | awx-manage shell
For reference, see https://github.com/ansible/awx-operator/blob/7d2d1b3c5e3766966bfec0f9f58037f654b93b59/roles/installer/tasks/initialize_django.yml#L21-L24
I have been searching the web for an answer now for quite a while, but this is giving me really headache:
I am using Ubuntu 12.04 and I want to execute a Python script from the terminal without using the full path.
So i added /home/kyril/python/scripts/ to the PATH variable through putting the following into ./bashrc:
kyrilpathvariable="/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/kyril/Python/scripts/:/home/kyril/Bash/scripts"
if [ "$kyrilpathvariable" = "$PATH" ]; then
echo PATH already exported
else
PATH=$PATH:/home/kyril/Python/scripts/
PATH=$PATH:/home/kyril/Bash/scripts/
export PATH
fi
(I know the if clause is not necessary but I did not like to have everything two times in my PATH if I type exec bash.)
Now the problem: this perfectly works for my Bash scripts, so after making them executable via chmod I can just type $ script.sh and it is executed. However if I type $ python3 script.py the following error is raised: python3: can't open file 'script.py': [Errno 2] No such file or directory
if I type in the full path to the script it works. Anybody has an idea what I am doing wrong? Do I have to add the directory to the PYTHONPATH? (As I understood this only helps for importing modules).
Thanks guys!
When invoking python3 directly, python runs the script file you told it to, without using $PATH to find it. PYTHONPATH is irrelevant--that's used for searching for Python modules.
I'm guessing you're having issues with the wrong interpreter getting invoked when you run script.py by itself. I don't know what the first line of your script is, but it should be this:
#!/usr/bin/env python3
Or if you need even finer control:
#!/usr/bin/env python3.2
And for Python 2 scripts:
#!/usr/bin/env python2
Or:
#!/usr/bin/env python2.7
You should check that these executables exist on your system before trying to use them.
I would guess that path variables are ignored when python searches for the input-file. Python starts searching for 'script.py' in the current directory, not knowing that there is a path variable declared for that file, and therefore cannot find it.
Unfortunately I'm not sure how to solve it but maybe someone more experienced with variables can enlighten us?
python3 $(type -P script.py)
Tells Bash to look in the PATH for the executable file and supply its location and name.
For example:
$ type -P script.py
/usr/local/bin/script.py
To avoid duplicate entries in the path, you can do:
for dir in Python Bash; do
dir_to_add="$HOME/$dir/scripts"
case ":$PATH:" in
*:"$dir_to_add":*) ;; # path already contains dir, do nothing
*) PATH+=":$dir_to_add" ;;
esac
done
I previously used to copy Python/Perl scripts to access from my bash script. Duplication is not a good idea I know! Is there a way to call them from bin or libs folder that we have set up?
For instance :
My python script resides in /home/ThinkCode/libs/python/script.py
My bash script resides in /home/ThinkCode/NewProcess/ProjectA/run.sh
Now I want to use/call script.py from run.sh
Thank you!
Make this the first line of your python script (bash will then know this is a python script and it should be run with python):
#/usr/bin/env python
EDIT: my bad, it should be #!/usr/bin/env python not #!/usr/bin/python. It is better to do it this way.
Then chmod your script with u+x (if not a+x).
Now your python script works as an executable. Your bash script, then, can call it like you'd call any executable.
Just do python /path/to/my/python/script.py.
In a bash script, you execute programs the same way you do from the bash command prompt.
/home/ThinkCode/libs/python/script.py
If this doesn't launch the script directly, you may need to add python to the beginning (like this: python /home/ThinkCode/libs/python/script.py) and/or ensure that the script is executable (with chmod +x /home/ThinkCode/libs/python/script.py).
I am working on Mac OS X and I have a Python script which is going to be called by other scripts and programs (Apple's launchd in particular). I could call it with
python /Users/xyz/long/absolute/path/to/script.py arg1 arg2
Since the location of the script might change, I want to decouple other scripts and the launchd configuration files from the actual location, so that a call to the script looks like
script arg1 arg2
Defining an alias for Bash in $HOME/.bash_profile does not work, since launchd does not know about the alias.
What is the best way to define a "sytem-wide alias" or something equivalent?
I usually make a symbolic link and put it in /usr/bin (assuming /usr/bin is part of your PATH)
(In a terminal. You may have to use sudo ln -s depending on the permissions.
ln -s /Users/xyz/long/absolute/path/to/script.py /usr/bin/script.py
If you take Rory's advice and put the #!/usr/bin/python at the beginning of the script, you'll also need to make the script executable.
chmod a+x /Users/xyz/long/absolute/path/to/script.py
As well as doing a symlink, you can put "#! /path/to/python" at the start of the script and make it executabe. Then you don't have to call it with "python /Users/big/long/path/script.py"