How to make an executable to use in a shell - Python - python

I have a Python script and I was wondering how I can make it executable; in other words how can I run it by using a shell like bash.
I know the first thing is to stick on the first line #! /usr/bin/env python but then do I need for example the functions to be in a specific order (i.e., the main one at the top or the bottom). What's more do I need to keep the extension .py for my python file (can I just call the function Dosomething?).
To be short, could you provide a simple guide, the important points someone has to take into account to make a Python file executable?

This is how I make an executable script. It doesn't take eggs or anything like that into account. It's just a simple script that I want to be able to execute. I'm assuming you are using linux.
#! /usr/bin/env python
import sys
def main():
#
# Do something ... Whatever processing you need to do, make it happen here.
# Don't shove everything into main, break it up into testable functions!
#
# Whatever this function returns, is what the exit code of the interpreter,
# i.e. your script, will be. Because main is called by sys.exit(), it will
# behave differently depending on what you return.
#
# So, if you return None, 0 is returned. If you return integer, that
# return code is used. Anything else is printed to the console and 1 (error)
# is returned.
#
if an_error_occurred:
return 'I\'m returning a string, it will be printed and 1 returned'
# Otherwise 0, success is returned.
return 0
# This is true if the script is run by the interpreter, not imported by another
# module.
if __name__ == '__main__':
# main should return 0 for success, something else (usually 1) for error.
sys.exit(main())
Now, if you're permissions are set correctly, you can execute this script.
One thing to realize is as your script is processed each line is executed in the interpreter. This is true, regardless of how the processor "gets it". That is importing a script as a module and executing it as a script essentially both work the same, in that they both execute each line of the module.
Once you realize your script is simply executing as it runs, you realize that the order of functions don't matter. A function declaration is a function declaration. It's when you call the function that matters.
So, in general, the layout of your script looks like this
def func1():
pass
def func2():
pass
def main():
return 0
if __name__ == '__main__':
sys.exit(main())
You create the functions you want to use first, then you use them. Hope it helps.

Delete the first space. That is,
#!/usr/bin/env python
Should be the very first line of your file. Then, make sure you make set the permisions for the the file to executable with:
chmod u+x your_script.py
Python scripts execute in sequential order. If you have a file filled with functions, common practice is to have something that looks like this at the very end of your file:
if __name__ == '__main__':
main()
Where main() starts execution of your script. The reason we do it this way, instead of a bare call to main() is that this allows you to make your script act like a module without any modification; if you just had a single line that called main(), your module would would execute the script's main. The if statement just checks if your script is running in the __main__ namespace, i.e., it is running as a script.

The only thing (like you said it) is to include:
#! /bin/env python
on the first line. And is not even mandatory, but recommended.
After that, you can just call it writing:
python [filename].py
in a terminal or in a bash file.

You'll also have to give it execution rights:
chmod u+x yourfile.py

Your code should follow the template
# any functions I want to define, and will be accessible when imported as module
# or run from command line
...
if __name__ == '__main__':
# things I want to do only when I run it from the command line
...
If you want to be able to run it without having to use python fileName.py but rather just ./fileName.py then you will want to make the first line of your file
#!/usr/bin/env python
And make the file executable by the user at least
chmod u+x fileName.py
If you do not add a .py extension to your file then it will still be runnable from the command line ... but not importable by other modules.

Place #!/usr/bin/python in the first line
You can name your python script anything, like: myPythonScript (No, you do not need to keep .py extension)
chmod +x myPythonScript
Run it: ./myPythonScript
Example: myPythonScript
#!/usr/bin/python
print "hello, world!"

You need to add sha bang as you described, e.g.
#!/usr/bin/python
or
#!/usr/bin/env python
as the first line in your file and you need to make it executable by running
chmod +x Dosomething
You do not need to do anything else, in particular file name may be anything including Dosomething. Your PATH probably doesn't include the directory where the file resides, so you should run it like this (assuming your current working directory is where the file is):
./Dosomething

Related

How to run multiple python scripts using single python(.py) script

I have written multiple python scripts that are to be run sequentially to achieve a goal. i.e:
my-directory/
a1.py,
xyz.py,
abc.py,
....,
an.py
All these scripts are in the same directory and now I want to write a single script that can run all these .py scripts in a sequence. To achieve this goal, I want to write a single python(.py) script but don't know how to write it. I have windows10 so the bash script method isn't applicable.
What's the best possible way to write an efficient migration script in windows?
using a master python script is a possibility (and it's cross platform, as opposed to batch or shell). Scan the directory and open each file, execute it.
import glob,os
os.chdir(directory) # locate ourselves in the directory
for script in sorted(glob.glob("*.py")):
with open(script) as f:
contents = f.read()
exec(contents)
(There was a execfile method in python 2 but it's gone, in python 3 we have to read file contents and pass it to exec, which also works in python 2)
In that example, order is determined by the script name. To fix a different order, use an explicit list of python scripts instead:
for script in ["a.py","z.py"]:
That method doesn't create subprocesses. It just runs the scripts as if they were concatenated together (which can be an issue if some files aren't closed and used by following scripts). Also, if an exception occurs, it stops the whole list of scripts, which is probably not so bad since it avoids that the following scripts work on bad data.
You can name a function for all the script 2 like this:
script2.py
def main():
print('Hello World!')
And import script2 function with this:
script1.py
from script2.py import *
main()
I hope this is helpful (tell me if I didn't answer to your question I'm Italian..)

Why doesn't the rest of the code after call() work? [duplicate]

I have a python script which when run, logs information on the terminal, i want to send this logging information to a text file,
To achieve this in the beginning of the file i am inserting
import subprocess
subprocess.call(['script', 'logfile'])
and at the end of the file,i put in,
subprocess.call(['exit'])
The problem with this is when it calls the first commandscript logfile,it terminates the script,
Any suggestions on how i could make this work would be really helpful,Thanks in advance
The problem is that subprocess.call isn't returning until the shell spawned by script exits, at which point your Python script will resume.
The simplest way to do what you want is to call script itself with your Python script as an argument. Instead of
#!/usr/bin/python
import subprocess
subprocess.call(['script', 'logfile'])
# Rest of your Python code
subprocess.call(['exit'])
you will use
#!/usr/bin/python
import os
import sys
if '_underscript' not in os.environ:
os.environ['_underscript'] = "yes"
cmd_args = ['script', 'logfile', 'python'] + sys.argv
os.execvp('script', cmd_args)
# Rest of your Python code
The environment variable prevents your script from entering an infinite loop of re-running itself with script. When you run your Python script, it first checks its environment for a variable that should not yet exist. If it doesn't, it sets that variable, then runs script to re-run the Python script. execvp replaces your script with the call to script; nothing else in the Python script executes. This second time your script runs, the variable _underscript does exist, meaning the if block is skipped and the rest of your script runs as intended.
Seems like that's the expected behaviour of subprocess.call(...). If you want to capture the output of the script to a file, you'll need to open a new file handler in write mode, and tell the subprocess.call where to direct the stdout, which is the terminal output you typically would see.
Try:
import subprocess
f = open('/tmp/mylogfile.log', 'w')
subprocess.call(['/path/to/script'], stdout=f)
f.close()
Then in the terminal you can run tail /tmp/mylogfile.log to confirm.
I'm not sure the last exit call is required for what you're trying to achieve.
You can read more in the python docs, depending which version of Python you're using. https://docs.python.org/2/library/subprocess.html
The file doesn't need to pre-exist. Hope that helps!

Running a script from another python

I just want to have some ideas to know how to do that...
I have a python script that parses log files, the log name I give it as an argument so that when i want to run the script it's like that.. ( python myscript.py LOGNAME )
what I'd like to do is to have two scripts one that contains the functions and another that has only the main function so i don't know how to be able to give the argument when i run it from the second script.
here's my second script's code:
import sys
import os
path = "/myscript.py"
sys.path.append(os.path.abspath(path))
import myscript
mainFunction()
the error i have is:
script, name = argv
valueError: need more than 1 value to unpack
Python (just as most languages) will share parameters across imports and includes.
Meaning that if you do:
python mysecondscript.py heeey that will flow down into myscript.py as well.
So, check your arguments that you pass.
Script one
myscript = __import__('myscript')
myscript.mainfunction()
script two
import sys
def mainfunction():
print sys.argv
And do:
python script_one.py parameter
You should get:
["script_one.py", "parameter"]
You have several ways of doing it.
>>> execfile('filename.py')
Check the following link:
How to execute a file within the python interpreter?

execute python script with argparse inside python script

I got two different python script, the first one is using argparse to get some additional argument (I will call it arg.py) and the second one is my main script (main.py).
I want to call arg.py inside main.py but I don't know how to do so. I take a look at the command execfile but I didn't manage to make it work.
I try to put
execfile('arg.py -h')
In main.py but python try to find the file 'arg.py -h' which doesn't exist. Does anyone know how to do that ?
Thanks in advance
You can run it as a separate process using subprocess.call or subprocess.Popen. If you don't want to run it as a child process, then it starts to get more complicated (depending on the structure of your arg.py script.
execfile takes the file you pass to it and includes it in the current script -- Much like a #include pre-processor directive in c/c++ (although this is done dynamically). One really ugly option using execfile would be:
#completely untested.
import sys
def run_script(script_name,*args):
_argv = sys.argv[:]
sys.argv = list(args)
execfile(script_name)
sys.argv = _argv

Running Python script from .BAT file, taking .BAT Filename as input

I got a Python script (test1.py) I need to run with a bat file (render.bat).
Question 1:
First, I had a definition in my test1.py and it always failed to run, nothing happened. Can someone kindly explain why?
import os
def test01 :
os.system('explorer')
and in the bat file:
python c:/test01.py
but as soon as I removed the def it worked. I just want to learn why this happened.
Question 2:
How can I take "render" string from render.bat as a string input for my python script so I can run something like :
import os
def test1(input) :
os.system("explorer " + input)
So the "input" is taken from the .BAT filename?
Functions don't actually do anything unless you call them. Try putting test01() at the end of the script.
%0 will give you the full name of the batch file called, including the .bat. Stripping it will probably be easier in Python than in the batch file.
Question1: Keyword def in python defines a function. However, to use a function you have to explicitly call it, i.e.
import os
def test01(): # do not forget ()
os.system('explorer')
test01() # call the function
1) You have to actually call the functions to achieve your task.
2) %0 refers to the running script. Therefor create a test.bat file like
# echo off
echo %0
Output = test.bat
You can strip the .bat extension from the output.

Categories