Call Python function from JavaScript code

289,925

Solution 1

All you need is to make an ajax request to your pythoncode. You can do this with jquery http://api.jquery.com/jQuery.ajax/, or use just javascript

$.ajax({
  type: "POST",
  url: "~/pythoncode.py",
  data: { param: text}
}).done(function( o ) {
   // do something
});

Solution 2

From the document.getElementsByTagName I guess you are running the javascript in a browser.

The traditional way to expose functionality to javascript running in the browser is calling a remote URL using AJAX. The X in AJAX is for XML, but nowadays everybody uses JSON instead of XML.

For example, using jQuery you can do something like:

$.getJSON('http://example.com/your/webservice?param1=x&param2=y', 
    function(data, textStatus, jqXHR) {
        alert(data);
    }
)

You will need to implement a python webservice on the server side. For simple webservices I like to use Flask.

A typical implementation looks like:

@app.route("/your/webservice")
def my_webservice():
    return jsonify(result=some_function(**request.args)) 

You can run IronPython (kind of Python.Net) in the browser with silverlight, but I don't know if NLTK is available for IronPython.

Solution 3

Typically you would accomplish this using an ajax request that looks like

var xhr = new XMLHttpRequest();
xhr.open("GET", "pythoncode.py?text=" + text, true);
xhr.responseType = "JSON";
xhr.onload = function(e) {
  var arrOfStrings = JSON.parse(xhr.response);
}
xhr.send();

Solution 4

Communicating through processes

Example:

Python: This python code block should return random temperatures.

# sensor.py

import random, time
while True:
    time.sleep(random.random() * 5)  # wait 0 to 5 seconds
    temperature = (random.random() * 20) - 5  # -5 to 15
    print(temperature, flush=True, end='')

Javascript (Nodejs): Here we will need to spawn a new child process to run our python code and then get the printed output.

// temperature-listener.js

const { spawn } = require('child_process');
const temperatures = []; // Store readings

const sensor = spawn('python', ['sensor.py']);
sensor.stdout.on('data', function(data) {

    // convert Buffer object to Float
    temperatures.push(parseFloat(data));
    console.log(temperatures);
});

Solution 5

You cannot run .py files from JavaScript without the Python program like you cannot open .txt files without a text editor. But the whole thing becomes a breath with a help of a Web API Server (IIS in the example below).

  1. Install python and create a sample file test.py

    import sys
    # print sys.argv[0] prints test.py
    # print sys.argv[1] prints your_var_1
    
    def hello():
        print "Hi" + " " + sys.argv[1]
    
    if __name__ == "__main__":
        hello()
    
  2. Create a method in your Web API Server

    [HttpGet]
    public string SayHi(string id)
    {
        string fileName = HostingEnvironment.MapPath("~/Pyphon") + "\\" + "test.py";          
    
        Process p = new Process();
        p.StartInfo = new ProcessStartInfo(@"C:\Python27\python.exe", fileName + " " + id)
        {
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };
        p.Start();
    
        return p.StandardOutput.ReadToEnd();                  
    }
    
  3. And now for your JavaScript:

    function processSayingHi() {          
       var your_param = 'abc';
       $.ajax({
           url: '/api/your_controller_name/SayHi/' + your_param,
           type: 'GET',
           success: function (response) {
               console.log(response);
           },
           error: function (error) {
               console.log(error);
           }
        });
    }
    

Remember that your .py file won't run on your user's computer, but instead on the server.

Share:
289,925

Related videos on Youtube

xralf
Author by

xralf

Updated on July 08, 2022

Comments

  • xralf
    xralf almost 2 years

    I'd like to call a Python function from JavaScript code, because there isn't an alternative in JavaScript for doing what I want. Is this possible? Could you adjust the below snippet to work?

    JavaScript code:

    var tag = document.getElementsByTagName("p")[0];
    text = tag.innerHTML;
    // Here I would like to call the Python interpreter with Python function
    arrOfStrings = openSomehowPythonInterpreter("~/pythoncode.py", "processParagraph(text)");
    

    ~/pythoncode.py contains functions using advanced libraries that don't have an easy to write equivalent in JavaScript:

    import nltk # is not in JavaScript
    def processParagraph(text):
      ...
      nltk calls
      ...
      return lst # returns a list of strings (will be converted to JavaScript array)
    
    • Fred Foo
      Fred Foo over 11 years
      No, browsers (fortunately) won't execute arbitrary Python code. You'll want to run that in a server.
    • John Dvorak
      John Dvorak over 11 years
      Javascript runs on the client. I assume the python runs on the server. You could send an ajax request to the server. It won't be fast.
    • Asad Saeeduddin
      Asad Saeeduddin over 11 years
      Using ajax, send text to a python script on your server. Set up the script to return data in an easy to parse (for js) notation (like JSON) and assign the result to arrOfStrings in the success handler.
    • John Dvorak
      John Dvorak over 11 years
      Also, finding a python engine for javascript won't be easy either
    • Admin
      Admin over 11 years
      You can run the official Python interpreter in the browser by compiling it using clang and Emscripten. This has been done before.
    • Paulo Scardine
      Paulo Scardine over 11 years
      You can run IronPython (kind of Python.Net) in the browser with silverlight, but I don't know if NLTK is available for IronPython.
    • SO_fix_the_vote_sorting_bug
      SO_fix_the_vote_sorting_bug about 4 years
      @FredFoo, What would actually be fortunate is if browsers didn't run ECMAScript (which is called JavaScript for rather dubious historical reasons.) What would also be fortunate is if browsers had been running a secure subset (which is what anyone means by running anything in a browser, your straw man notwithstanding) of Python since the '90s so we wouldn't have to be dealing with the current web mess.
    • Extreme
      Extreme almost 3 years
      For those finding this on Google, checkout the modern answer here : stackoverflow.com/a/68497604/11173996
  • xralf
    xralf over 11 years
    It looks interesting. Where could be the call of processParagraph(text) so that the return values ends in the variable arrOfStrings?
  • xralf
    xralf over 11 years
    I'm running this code in firebug, but it logs []
  • xralf
    xralf over 11 years
    OK, so how is it right? My Python file contains the correct function. Should I call the function in Python and the argument will be sys.argv[1]?
  • NuclearPeon
    NuclearPeon about 11 years
    Could you elaborate? When calling a python function via ajax post, does it call the __ main __ method? Because main cannot return a string. Can we expect to get any return values back? Does the data attribute correspond to the **kwargs dictionary in python, so we must have a method that accepts that? Otherwise, how do we specify the function in the python module?
  • Matteo
    Matteo over 9 years
    Thanks for the answer, but in order for the python script to execute it has to be deployed by a web server that supports it via CGI or WSGI. Could you please include in your answer how to solve that problem?
  • Matteo
    Matteo over 9 years
    Oh I'd be very happy to edit your answer if I knew how to do that, I was hoping you could provide some advice, cause I'm getting this error XMLHttpRequest cannot load file:~/pythoncode.py. Cross origin requests are only supported for protocol schemes: http, data, chrome-extension, https, chrome-extension-resource and even though I understood what the problem is don't know how to solve it. Any useful pointer? Thanks a lot. (btw...chessheaven seems really awesome! I'll try it out for sure, good thing you put a cute girl in your profile picture ;))
  • Gustavo6046
    Gustavo6046 over 3 years
    @NuclearPeon I suspect it's actually Python CGI, so it would print, not return. :D