Execute python code from within a shell script - python

I want to have some python code run within a shell script. I don't want to rely on an external file to be ran. Is there any way to do that?
I did a ton of googling, but there aren't any clear answers. This code is what I find... But it relies on the external python script to be ran. I want it all within one file.
python python_script.py

You can use a so-called "here document":
#!/usr/bin/env bash
echo "hello from bash"
python3 - <<'EOF'
print("hello from Python 3")
EOF
The single quotes around the first EOF prevent the usual expansions and command substitions in a shell script.
If you want those to happen, simply remove them.

If you mean within a BASH shell script without executing any external dependencies, I am afraid you're out of luck, since BASH only interprets its own scripting language.
Your question is somewhat like asking "Can I run a Java .class file without the JVM"? Obviously, you will always have the external dependency of the JRE/JVM. This is the same case, you depend on the external Python compiler and interpreter.
Optionally, you have the option of including the python script inline, but it would still require the python executable.
This works:
python -c 'print("Hi")'
Or this with BASH redirection:
python <<< 'print("Hi")'

Related

Cannot run MATLAB from bash script under Windows/MSYS2

I need to run a MATLAB script from a Python script. I don't care about the output of it nor do I need to give it any arguments.
However, MATLAB R2016B's "engine" does not support Python 3.7 (Upgrading Matlab or down-grading python is not an option at this time)
So, I decided to make a shell script that runs it:
#!matlab -nodisplay -nodesktop -r 'try; myMatlabScript; catch; end; quit'
Now I need to run a bash script from Python. To do so, I did:
import subprocess
subprocess.call("./mybashscript.sh")
(And yes, the python script is at the same level as the shell script)
The python script does not complain directly. However, I do get the following:
'.' is not recognized as an internal or external command, operable program or batch file.
Which to me means that since Windows doesn't directly have bash, it doesn't know what to do with this shell script. I am not sure how to handle this. Some way to tell Python to use MSYS instead of Windows for the shell?
And thus the MATLAB script does not appear to run at all.
When I attempt under Linux (just for testing, I can't run it here for performance reasons), I get:
./mybashscript.sh: matlab: bad interpreter: No such file or directory
Is it possible this is because I didn't do the command addpath(genpath('.'))? If so, I'm not sure how I would do that in the shell script, and some help would be appreciated.
Or some other better solution would also be great.
1: Needed to re-name mybashscript.sh to mybashscript.bat
2: Needed to change the sub-process call to subprocess.call("mybashscript.bat") (as ./ was confusing the windows shell)
3: Needed to add the path properly. Here is what the batch script looked like:
matlab -nodisplay -nodesktop -r "addpath(genpath('C:/path/to/myscript')); myMatlabScript"
The double quotes are neccesary so the single quotes inside genpath do not cause it to end early.
And that was it!
EDIT: You can add -wait in the batch file to get the script to wait until it is complete before handing back to the Python script.

Using a compiled Python shell in Linux

Is it possible to use a "more complex" shell than just a single command shell? We have written a python shell that is a command loop, and it works fine in /etc/passwd like this:
user:x:1000:1000::/home/user:/usr/bin/ourshell.py
Of course the Python file has the shebang line for /usr/bin/python in it. However, we'd like to compile the Python shell into a .pyc file to save a bit of time on execution in login. So, after compiling, I've been trying to "quote" the shell line in /etc/passwd as "python ourshell.pyc", and I even tried making the shell a bash script which simply executes that same command (with the initial arguments).
Of course none of this has worked. When we SSH in, there is always some kind of error. Is there any special trick to what I am trying to do?
CPython's .pyc files are not text, and do not allow use of a shebang line. The traditional method is to have your called script be tiny; it would simply import a module with the rest of the program, which can then be precompiled. For instance, here is the main script of xonsh:
#!/usr/bin/env python3 -u
from xonsh.main import main
main()
This script takes negligible time to compile. It is also possible to run installed modules using -m, but that takes module names, not filenames, so is not suitable for a shebang script.
I suggest to code a small C wrapper program running your python shell.
(notice that execve(2) forbids nested shebang interpreters; I don't know if that applies for your case)
Look into your log files, probably /var/log/messages and /var/log/auth.log
You may also need to explicitly add (the compiled C executable for the wrapper) to /etc/shells; see shells(5)
Look also into scsh.
Your sshd daemon is probably using Linux Plugin Authentification Modules. So read more about PAM.
Create a file /usr/bin/shell_wrapper that contains this one line:
#!/usr/bin/python /usr/bin/ourshell.pyc
The compiled bytecode ourshell.pyc has to live in /usr/bin, or else change the path accordingly. The python path should go to the same version that compiled the bytecode.
Then make sure to have your /etc/passwd use /usr/bin/shell_wrapper for the shell executable:
user:x:1000:1000::/home/user:/usr/bin/shell_wrapper

How to run emacs lisp interpreter in shell?

I am trying to run some examples of programs in Emacs Lisp.
How can we run its interpreter in shell, and then run some commands line by line with output immediately available? Is it similar to Python, for which we first type python to run its interpreter, and then type any commands inside it?
how can we run such a program without we entering into its interpreter? Is it similar to Python, for which we can run python myscript.py in the shell?
Thanks.
1) Use the REPL inside Emacs: M-x ielm RET
I don't know if there's a shell-based REPL, but you could possibly make one without too much difficulty.
Consider:
$ emacs -Q --daemon=myrepl
$ emacsclient --socket-name=myrepl --eval '(princ user-emacs-directory)'
"~/.emacs.d/"
$ emacsclient --socket-name=myrepl --eval '(kill-emacs)'
(but really, just use ielm).
2) If you actually have shell scripts written in elisp, then take a look at this Q&A: Run elisp program without Emacs?
But that's not a common thing to do, and there are lots of reasons not to write elisp scripts.
If you're unfamiliar with Emacs and simply have a .el file you don't know what to do with, this almost certainly isn't what you want to do. Elisp libraries are nearly always intended to be loaded inside of Emacs, rather than executed from the shell.
(If you're at all unsure, I recommend that you update your question with an example, as you're possibly asking the wrong questions.)

How to distribute my Python/shell script?

I have written a very simple command line utility for myself. The setup consists of:
A single .py file containing the application/source.
A single executable (chmod +x) shell script which runs the python script.
A line in my .bash_profile which aliases my command like so: alias cmd='. shellscript' (So it runs in the same terminal context.)
So effectively I can type cmd to run it, and everything works great.
My question is, how can I distribute this to others? Obviously I could just write out these instructions with my code and be done with it, but is there a faster way? I've occasionally seen those one-liners that you paste into your console to install something. How would I do that? I seem to recall them involving curl and piping to sh but I can't remember.
Upload your script to something like ideone. Then tell your friend to pipe it into python. Example script:
def print_message():
print "This is my very special script!"
if __name__ == "__main__":
print_message()
Example of running script:
username#server:~$ curl http://ideone.com/plain/O2n3Pg 2>/dev/null | python
This is my very special script!
chmod +x cmd.py
then they can type ./cmd.py
they can also use it piped.
I would add that unix users would probably already know how to make a file executable and run it, so all you'd have to do is make the file available to them.
Do make sure they know what version(s) of python they need to run your script.

Wrap all commands entered within a Bash-Shell with a Python script

What i'd like to have is a mechanism that all commands i enter on a Bash-Terminal are wrapped by a Python-script. The Python-script executes the entered command, but it adds some additional magic (for example setting "dynamic" environment variables).
Is that possible somehow?
I'm running Ubuntu and Debian Squeezy.
Additional explanation:
I have a property-file which changes dynamically (some scripts do alter it at any time). I need the properties from that file as environment variables in all my shell scripts. Of course i could parse the property-file somehow from shell, but i prefer using an object-oriented style for that (especially for writing), as it can be done with Python (and ConfigObject).
Therefore i want to wrap all my scripts with that Python script (without having to modify the scripts themselves) which handles these properties down to all Shell-scripts.
This is my current use case, but i can imagine that i'll find additional cases to which i can extend my wrapper later on.
The perfect way to wrap every command that is typed into a Bash Shell is to change the variable PROMPT_COMMAND inside the .bashrc. For example, if I want to do some Python stuff before every command, liked asked in my question:
.bashrc:
# ...
PROMPT_COMMAND="python mycoolscript.py; $PROMPT_COMMAND;"
export $PROMPT_COMMAND
# ...
now before every command the script mycoolscript.py is run.
Use Bash's DEBUG trap. Let me know if you need me to elaborate.
Edit:
Here's a simple example of the kinds of things you might be able to do:
$ cat prefix.py
#!/usr/bin/env python
print "export prop1=foobar"
print "export prop2=bazinga"
$ cat propscript
#!/bin/bash
echo $prop1
echo $prop2
$ trap 'eval "$(prefix.py)"' DEBUG
$ ./propscript
foobar
bazinga
You should be aware of the security risks of using eval.
I don't know of anything but two things that might help you follow
http://sourceforge.net/projects/pyshint/
The iPython shell has some functionality to execute shell commands in the iterpreter.
There is no direct way you can do it .
But you can make a python script to emulate a bash terminal and you can use the beautiful "Subprocess" module in python to execute commnands the way you like

Categories