556

I have this code:

def hello():
    return 'Hi :)'

How would I run this directly from the command line?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Steven
  • 5,633
  • 3
  • 15
  • 5

18 Answers18

828

With the -c (command) argument (assuming your file is named foo.py):

$ python -c 'import foo; print foo.hello()'

Alternatively, if you don't care about namespace pollution:

$ python -c 'from foo import *; print hello()'

And the middle ground:

$ python -c 'from foo import hello; print hello()'
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • 58
    I noted that on windows shell, you need a double quote instead of single. `$python -c "import foo;foo.hello()" ` – Arindam Roychowdhury Jun 01 '16 at 12:59
  • 7
    What if the file is not in the local directory or on the PYTHONPATH? – Konstantin Jul 07 '17 at 14:32
  • On Ubuntu Linux you also have to use double quotes if you run the command from inside a Qt app for example. – Olaf Japp Jul 17 '17 at 11:52
  • 2
    The second one is a more general answer. I have a script defined multiple customer functions, and only call one depending on my need – xappppp Apr 15 '18 at 04:16
  • 7
    For some reason, this didn't work for me, while replacing `print foo.hello()` with `print(foo.hello())` did. I don't have the python knowledge to explain why this is, so if someone else could explain what can be going on, that would be greatly appreciated – Jasper Jan 04 '20 at 03:13
  • 4
    @Jasper, you must be using python 3 which needs print function to have its arguments in parenthesis – Aakanksha Choudhary Mar 11 '20 at 14:10
  • 4
    @Aakanksha Thanks for the explanation, and that definitely makes sense. Does it seem right to edit the answer to include the parentheses? That would make it compatible with both python 2 and 3 if I'm not mistaken. (At moments like this, I would have liked to be able to make an edit suggestion.) – Jasper Mar 11 '20 at 21:51
  • 1
    @Jasper, thank you very much for your efforts in curating the site, but please do not edit this question only to bring it in line with Python 3. It was posted nearly a decade ago when Python 3 was the exception, not the rule, and I would like to preserve it as such, if only to demonstrate that languages do evolve, older versions do stick around, and it is useful to remember history as we go along, or so I believe. – Frédéric Hamidi Mar 12 '20 at 01:08
  • 14
    While this answer was written a decade ago, it's a top Google result today. And I believe that's what this site is intended to be: a place to find relevant answers, not a testament to evolving languages. The FAQ actually mentions keeping a post up to date as an important reason to do edits. I'd say adding a section about python versions to this answer would be a better way to enshrine the changes in the language, but I thought changing the code to be cross-version compatible was a more elegant solution. And the edit history will always stand as a testament of what was. – Jasper Mar 13 '20 at 03:32
  • @Jasper, It as such doesn't hurt to have solution for both versions specified version wise but your comment there where you mentioned adding parenthesis gives correct result is valuable enough for someone who needs it. – Aakanksha Choudhary Mar 13 '20 at 16:52
  • 1
    @AakankshaChoudhary I guess if that's the shared opinion of all others who comment here, I won't touch a thing. I do disagree, though. If it had been some weird edge case, I would have agreed that a comment was enough. As it stands, though, every single user (that's not using a EOL version of python) with this question will be greeted with a non-functional answer (and have to dig around and click "show more comments" to find how to fix it). I feel it's to SO's detriment to not have it in the post's body as well as actively confusing users... – Jasper Mar 14 '20 at 09:59
  • Though it seems to be obvious, it would be nice to mention that `python -c 'from foo import hello; print hello(); print hello()'` could be used as well to print out two hellos after each other. Typically, this helps you if you have a setup or load function in between, which you need to initialize a module. – HauiB Nov 05 '20 at 13:18
  • @Konstantin Just add `cd /path/to/your/folder && ` before. – Oriol Vilaseca Jun 22 '21 at 10:47
  • 2
    I only say as much, this does not work in Python 3 (or any other Python version that wasn't sunset 2 years ago). – bers Mar 03 '22 at 15:52
  • 4
    This is ridiculous. This answer has more than 700 upvotes, but cannot work on any currently supported python version. Please accept the minor edits, which actually fix the broken code. – Eric Duminil Jun 02 '22 at 12:55
  • Agree, this is not a code museum. Python 2 is dead. There is no benefit to treating answers as time capsules. – Steven Dec 05 '22 at 09:13
170

Just put hello() somewhere below the function and it will execute when you do python your_file.py

For a neater solution you can use this:

if __name__ == '__main__':
    hello()

That way the function will only be executed if you run the file, not when you import the file.

Wolph
  • 78,177
  • 11
  • 137
  • 148
  • 6
    And what if `hello()` takes arguments that should be supplied by the command line? – pretzlstyle Feb 10 '18 at 02:29
  • 3
    In that case you can send `sys.argv` to the method. Or access it from the hello method – Wolph Feb 10 '18 at 08:48
  • 3
    One difference between this answer and the import foo solution is that import foo allows calling an arbitrary function in foo without modifying foo. – plafratt Apr 26 '18 at 15:37
  • That's true, but I wouldn't recommend that solution beyond test purposes – Wolph Apr 26 '18 at 20:12
  • @Wolph hey with this structure, how do I execute a seperate function (not included inside `hello()`) and run it from the command line? – Souvik Ray May 23 '18 at 07:03
  • You can't do that directly. You can do some `sys.argv` parsing (with `argparse` for example) to execute different methods. – Wolph May 23 '18 at 10:25
99

add this snippet to the bottom of your script

def myfunction():
    ...


if __name__ == '__main__':
    globals()[sys.argv[1]]()

You can now call your function by running

python myscript.py myfunction

This works because you are passing the command line argument (a string of the function's name) into locals, a dictionary with a current local symbol table. The parantheses at the end will make the function be called.

update: if you would like the function to accept a parameter from the command line, you can pass in sys.argv[2] like this:

def myfunction(mystring):
    print(mystring)


if __name__ == '__main__':
    globals()[sys.argv[1]](sys.argv[2])

This way, running python myscript.py myfunction "hello" will output hello.

Pikamander2
  • 7,332
  • 3
  • 48
  • 69
Noam Hacker
  • 4,671
  • 7
  • 34
  • 55
  • 1
    Is it possible for this method to accept a parameter for the function? Such as `myfunction(12)` – Major Major Apr 18 '19 at 02:49
  • 1
    @MajorMajor I have updated the answer to include how to do this – Noam Hacker Apr 18 '19 at 14:10
  • is this any danger doing this in live production? Like want to make it as a unit test. – Ardhi Sep 22 '19 at 02:22
  • 1
    [D. Jagatiya's answer](https://stackoverflow.com/a/65108366/79125) has a more complete example for passing args -- it passes all of the args to the function and you get a reasonable error if the user didn't pass the right number of arguments. – idbrii Jan 12 '22 at 22:31
  • 2
    @Ardhi: I wouldn't do this in prod since it allows calling any global function in your file which makes it brittle. Use [pytest for easy testing setup](https://docs.pytest.org/en/6.2.x/getting-started.html#create-your-first-test). – idbrii Jan 12 '22 at 22:36
81

python -c 'from myfile import hello; hello()' where myfile must be replaced with the basename of your Python script. (E.g., myfile.py becomes myfile).

However, if hello() is your "permanent" main entry point in your Python script, then the usual way to do this is as follows:

def hello():
    print "Hi :)"

if __name__ == "__main__":
    hello()

This allows you to execute the script simply by running python myfile.py or python -m myfile.

Some explanation here: __name__ is a special Python variable that holds the name of the module currently being executed, except when the module is started from the command line, in which case it becomes "__main__".

Tamás
  • 47,239
  • 12
  • 105
  • 124
  • 2
    What is the difference between `python -m foo -c 'foo.bar()'` and `python -c 'import foo; foo.bar()'`? I get different behavior where it seems the -c argument is ignored in the first case. – Abram Jun 17 '17 at 07:56
  • @Abram `-m mod : run library module as a script (terminates option list)` – bers Jan 19 '23 at 12:09
36

I wrote a quick little Python script that is callable from a bash command line. It takes the name of the module, class and method you want to call and the parameters you want to pass. I call it PyRun and left off the .py extension and made it executable with chmod +x PyRun so that I can just call it quickly as follow:

./PyRun PyTest.ClassName.Method1 Param1

Save this in a file called PyRun

#!/usr/bin/env python
#make executable in bash chmod +x PyRun

import sys
import inspect
import importlib
import os

if __name__ == "__main__":
    cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
    if cmd_folder not in sys.path:
        sys.path.insert(0, cmd_folder)

    # get the second argument from the command line      
    methodname = sys.argv[1]

    # split this into module, class and function name
    modulename, classname, funcname = methodname.split(".")

    # get pointers to the objects based on the string names
    themodule = importlib.import_module(modulename)
    theclass = getattr(themodule, classname)
    thefunc = getattr(theclass, funcname)

    # pass all the parameters from the third until the end of 
    # what the function needs & ignore the rest
    args = inspect.getargspec(thefunc)
    z = len(args[0]) + 2
    params=sys.argv[2:z]
    thefunc(*params)

Here is a sample module to show how it works. This is saved in a file called PyTest.py:

class SomeClass:
 @staticmethod
 def First():
     print "First"

 @staticmethod
 def Second(x):
    print(x)
    # for x1 in x:
    #     print x1

 @staticmethod
 def Third(x, y):
     print x
     print y

class OtherClass:
    @staticmethod
    def Uno():
        print("Uno")

Try running these examples:

./PyRun PyTest.SomeClass.First
./PyRun PyTest.SomeClass.Second Hello
./PyRun PyTest.SomeClass.Third Hello World
./PyRun PyTest.OtherClass.Uno
./PyRun PyTest.SomeClass.Second "Hello"
./PyRun PyTest.SomeClass.Second \(Hello, World\)

Note the last example of escaping the parentheses to pass in a tuple as the only parameter to the Second method.

If you pass too few parameters for what the method needs you get an error. If you pass too many, it ignores the extras. The module must be in the current working folder, put PyRun can be anywhere in your path.

32

We can write something like this. I have used with python-3.7.x

import sys

def print_fn():
    print("Hi")

def sum_fn(a, b):
    print(a + b)

if __name__ == "__main__":
    args = sys.argv
    # args[0] = current file
    # args[1] = function name
    # args[2:] = function args : (*unpacked)
    globals()[args[1]](*args[2:])

python demo.py print_fn
python demo.py sum_fn 5 8
D. Jagatiya
  • 483
  • 6
  • 7
15

Let's make this a little easier on ourselves and just use a module...

Try: pip install compago

Then write:

import compago
app = compago.Application()

@app.command
def hello():
    print "hi there!"

@app.command
def goodbye():
    print "see ya later."

if __name__ == "__main__":
    app.run()

Then use like so:

$ python test.py hello
hi there!

$ python test.py goodbye
see ya later.

Note: There's a bug in Python 3 at the moment, but works great with Python 2.

Edit: An even better option, in my opinion is the module fire by Google which makes it easy to also pass function arguments. It is installed with pip install fire. From their GitHub:

Here's a simple example.

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

Then, from the command line, you can run:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30
Charles Clayton
  • 17,005
  • 11
  • 87
  • 120
  • 2
    +1. Fire even has a way to call a function without changing the script: `python -m fire file_name method_name`. It also has a built-in argparser. – user3265569 Apr 24 '20 at 12:15
7

Interestingly enough, if the goal was to print to the command line console or perform some other minute python operation, you can pipe input into the python interpreter like so:

echo print("hi:)") | python

as well as pipe files..

python < foo.py

*Note that the extension does not have to be .py for the second to work. **Also note that for bash you may need to escape the characters

echo print\(\"hi:\)\"\) | python
Torie J
  • 106
  • 1
  • 3
7

I had a requirement of using various python utilities (range, string, etc.) on the command line and had written the tool pyfunc specifically for that. You can use it to enrich you command line usage experience:

 $ pyfunc -m range -a 1 7 2
 1
 3
 5

 $ pyfunc -m string.upper -a test
 TEST

 $ pyfunc -m string.replace -a 'analyze what' 'what' 'this'
 analyze this
iLoveTux
  • 3,552
  • 23
  • 31
Saurabh Hirani
  • 1,198
  • 14
  • 21
6

If you install the runp package with pip install runp its a matter of running:

runp myfile.py hello

You can find the repository at: https://github.com/vascop/runp

vascop
  • 4,972
  • 4
  • 37
  • 50
5

This script is similar to other answers here, but it also lists the available functions, with arguments and docstrings:

"""Small script to allow functions to be called from the command line.
Run this script without argument to list the available functions:

    $ python many_functions.py
    Available functions in many_functions.py:

    python many_functions.py a  : Do some stuff

    python many_functions.py b  : Do another stuff

    python many_functions.py c x y : Calculate x + y

    python many_functions.py d  : ?

Run this script with arguments to try to call the corresponding function:

    $ python many_functions.py a
    Function a

    $ python many_functions.py c 3 5
    3 + 5 = 8

    $ python many_functions.py z
    Function z not found
"""

import sys
import inspect

#######################################################################
#                         Your functions here                         #
#######################################################################

def a():
    """Do some stuff"""
    print("Function a")

def b():
    """Do another stuff"""
    a()
    print("Function b")

def c(x, y):
    """Calculate x + y"""
    print(f"{x} + {y} = {int(x) + int(y)}")

def d():
    # No doc
    print("Function d")

#######################################################################
#         Some logic to find and display available functions          #
#######################################################################

def _get_local_functions():
    local_functions = {}
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isfunction(obj) and not name.startswith('_') and obj.__module__ == __name__:
            local_functions[name] = obj
    return local_functions

def _list_functions(script_name):
    print(f"Available functions in {script_name}:")
    for name, f in _get_local_functions().items():
        print()
        arguments = inspect.signature(f).parameters
        print(f"python {script_name} {name} {' '.join(arguments)} : {f.__doc__ or '?'}")


if __name__ == '__main__':
    script_name, *args = sys.argv
    if args:
        functions = _get_local_functions()
        function_name = args.pop(0)
        if function_name in functions:
            function = functions[function_name]
            function(*args)
        else:
            print(f"Function {function_name} not found")
            _list_functions(script_name)
    else:
        _list_functions(script_name)

Run this script without argument to list the available functions:

$ python many_functions.py
Available functions in many_functions.py:

python many_functions.py a  : Do some stuff

python many_functions.py b  : Do another stuff

python many_functions.py c x y : Calculate x + y

python many_functions.py d  : ?

Run this script with arguments to try to call the corresponding function:

$ python many_functions.py a
Function a

$ python many_functions.py c 3 5
3 + 5 = 8

$ python many_functions.py z
Function z not found
Eric Duminil
  • 52,989
  • 9
  • 71
  • 124
3

Something like this: call_from_terminal.py

# call_from_terminal.py
# Ex to run from terminal
# ip='"hi"'
# python -c "import call_from_terminal as cft; cft.test_term_fun(${ip})"
# or
# fun_name='call_from_terminal'
# python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
def test_term_fun(ip):
    print ip

This works in bash.

$ ip='"hi"' ; fun_name='call_from_terminal' 
$ python -c "import ${fun_name} as cft; cft.test_term_fun(${ip})"
hi
Al Conrad
  • 1,528
  • 18
  • 12
3

Below is the Odd_Even_function.py file that has the definition of the function.

def OE(n):
    for a in range(n):
        if a % 2 == 0:
            print(a)
        else:
            print(a, "ODD")

Now to call the same from Command prompt below are the options worked for me.

Options 1 Full path of the exe\python.exe -c "import Odd_Even_function; Odd_Even_function.OE(100)"

Option 2 Full path of the exe\python.exe -c "from Odd_Even_function import OE; OE(100)"

Thanks.

Alper Kucukkomurler
  • 1,706
  • 2
  • 13
  • 19
2

It is always an option to enter python on the command line with the command python

then import your file so import example_file

then run the command with example_file.hello()

This avoids the weird .pyc copy function that crops up every time you run python -c etc.

Maybe not as convenient as a single-command, but a good quick fix to text a file from the command line, and allows you to use python to call and execute your file.

1

This function cannot be run from the command line as it returns a value which will go unhanded. You can remove the return and use print instead

Shubham
  • 19
  • 1
-1

Use the python-c tool (pip install python-c) and then simply write:

$ python-c foo 'hello()'

or in case you have no function name clashes in your python files:

$ python-c 'hello()'
jadn
  • 117
  • 1
  • 3
-3

First you have to call the function as they told you or the founction will display nothing in the output, after that save the file and copy the path of the file by right click to the folder of the file and click on"copy file" then go to terminal and write: - cd "the path of the file" - python "name of the file for example (main.py)" after that it will display the output of your code.

ShahadM
  • 9
  • 1
-9

Make your life easier, install Spyder. Open your file then run it (click the green arrow). Afterwards your hello() method is defined and known to the IPython Console, so you can call it from the console.

Ivana
  • 643
  • 10
  • 27