I am new to web programming.
Writing a simple ajax call to run a python function via 2 files
javascriptPython3.html & javascriptPython3.py
Client is a macbook & firefox 80.0.1
Webserver is a raspberry pi Apache/2.4.25 (Raspbian) Server at rbp Port 80
On the server I run:
export FLASK_DEBUG=1
export FLASK_APP=javascriptPython3.py
flask run -h 192.168.1.6
* Serving Flask app "javascriptPython3"
* Forcing debug mode on
* Running on http://192.168.1.6:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: 318-477-733
192.168.1.3 - - [10/Dec/2022 14:44:55] "GET / HTTP/1.1" 200 -
192.168.1.3 - - [10/Dec/2022 14:44:57] "GET / HTTP/1.1" 200 -
192.168.1.3 - - [10/Dec/2022 14:44:58] "GET / HTTP/1.1" 200 -
On the client macbook browser:
http://192.168.1.6:5000/
Each Time I reload the webpage, I get an output line in the flask run.
So far so good.
But when I browse to javascriptPython3.html on the client, and click the button, I get 404 not found in the browser console.
If I change the ajax url to "javascriptPython3.py" I get 500 Internal Server error.
#!/usr/bin/env python3
#from flask import Flask, request, render_template
from flask import Flask
app = Flask(__name__)
#app.route('/', methods=['GET','POST'])
def makeupper():
# javascriptdata=request
# javascriptdata=javascriptdata.upper()
outputfile = open("javascriptPython.out", "a")
outputfile.write("Hello from Python\n\n")
return "ABCCC"
javascriptPython3.html:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
function successFun(pythonResponse) {
window.alert(pythonResponse);
document.getElementById('output1').value = pythonResponse;
}
function runPython() {
window.alert("We just called runPython()");
$.ajax({
type: "POST",
url: "/javascriptPython3.py",
// url: "/",
// data: "abc",
success: successFun()
});
}
</script>
</head>
<body>
<p> run python from javascrpt </p>
<br>
<input type="button" onClick="runPython()" value="Run Python" />
<br>
<br>
<p> Output text </p>
<textarea id="output1" rows="4" cols="50"> </textarea>
</body>
</html>
I was expecting to see javascriptPython.out get appended everytime
I clicked the button.
It got appended when I kept reloading http://192.168.1.6:5000/ just as I wanted it to
But when I browse to javascriptPython3.html on the client
That is correct. In your code, there is no route for javascriptPython3.html
A very high level/simplistic explanation
Flask returns (serves up) content based on paths (routes) you have defined in your python code. It can return content as plain text or it can return the content via a template (html page) i.e. render_template(<html_page>)
In your code, you have only defined one route - #app.route('/' which corresponds to http://192.168.1.6:5000/ . Think of it this way - anything you have defined in as a route comes after your server address which is http://192.168.1.6:5000
If you want to navigate to javascriptPython3.html i.e. you want to be able to type the url http://192.168.1.6:5000/javascriptPython3.html, then you have to define a route for it in your code i.e. you need something like app.route('/javascriptPython3.html')
Since it looks like you want to display javascriptPython3.html when you open your server (i.e when you go to your root i.e. /), you should modify your existing code to
from flask import Flask, request, render_template
app = Flask(__name__)
#app.route('/', methods=['GET','POST'])
def makeupper():
outputfile = open("javascriptPython.out", "a")
outputfile.write("Hello from Python\n\n")
return render_template('javascriptPython3.html')
I finally got it working ; Again I was trying to simply route to (run) a python function via ajax call.
I just needed to use a complete URL with IP and port, pointing to the apache server in my html file
AJAX URL: url: "http://192.168.1.9:5000/foo",
python route: #app.route('/foo', methods=['GET','POST'])
Below are the 2 files that work
export FLASK_APP=javascriptPython3.py
export FLASK_DEBUG=1
flask run -h 192.168.1.9
Browse to: http://192.168.1.9/javascriptPython3.html
#!/usr/bin/env python3
from flask import Flask, request, render_template
app = Flask(__name__)
#app.route('/foo', methods=['GET','POST'])
def foo():
# javascriptdata=request
# javascriptdata=javascriptdata.upper()
outputfile = open("javascriptPython.out", "a")
outputfile.write("Hello from Python\n\n")
return "ABCCC"
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.
min.js"></script>
<script>
function successFun(pythonResponse) {
window.alert(pythonResponse);
document.getElementById('output1').value = pythonResponse;
}
function runPython() {
window.alert("We just called runPython()");
$.ajax({
type: "GET",
url: "http://192.168.1.9:5000/foo",
// data: "abc",
success: successFun()
})
}
</script>
</head>
<body>
<p> run python from javascrpt </p>
<br>
<input type="button" onClick="runPython()" value="Run Python" />
<br>
<br>
<p> Output text </p>
<textarea id="output1" rows="4" cols="50"> </textarea>
</body>
</html>
Related
I run the following flask app on local host. I then hit the app on address/place_job/ with a http request. afterwards i go on my browser and look up address/track_site/job/0
expected behavior: The word "foo" show up immediately.
actual behavior: The browser (edge / Chrome) waits / spins until the thread finishes, and then immediately displays the word foo
Question: Why is the actual behavior happening, instead of the expected behavior, and how do i fix it? Preferably without sorting to celery or the likes.
I don't understand why this happens. What really bugs my mind, is that the expected behavior occurs If i delete the <script> line in the .HTML file. I have tested it with threading.Thread, as well as the threadpool executor from the flask-executor package.
minimal_app.py:
from flask import Flask, render_template
from threading import Thread
from time import time
app = Flask(__name__)
def func():
print("started")
start_time = time()
while time()-start_time<20: pass
print("ended")
#app.route('/place_job/')
def place_job():
Thread(target=func).start()
return "OK"
#app.route('/track_site/job/0')
def track_job():
return render_template('minimal_template.html')
static/templates/minimal_template.html
<!DOCTYPE html>
<html lang="en">
<body>
<h1 id="id1"> Job Page </h1>
<script type="text/javascript" src="/static/js/const.js"></script>
<p id="id2"> foo </p>
</body>
</html>
static/js/const.js
const x = 0;
edit
Below is the flask log after requesting /place_job/ and afterwards navigating to /track_site/job/0 :
127.0.0.1 - - [22/Apr/2022 20:15:04] "GET /place_job HTTP/1.1" 308 -
127.0.0.1 - - [22/Apr/2022 20:15:04] "GET /place_job/ HTTP/1.1" 200 -
started
127.0.0.1 - - [22/Apr/2022 20:15:12] "GET /track_site/job/0 HTTP/1.1" 200 -
ended
127.0.0.1 - - [22/Apr/2022 20:15:24] "GET /static/js/const.js HTTP/1.1" 304 -
I'm working on Flask and I'm stuck in a strange situation.
I'm trying to change an image with javascript but flask gives me these errors:
... 12:05:34] "GET / HTTP/1.1" 200 -
... 12:05:38] "GET /img/immagine.jpg HTTP/1.1" 404 -
JS:
var btnAddImage = document.getElementById("btnAddImage");
btnAddImage.onclick = function() {
var img = document.createElement("img");
img.src = "/static/img/immagine.jpg.jpg";
document.getElementById("asi").appendChild(img);
};
As you can see in the path it's specified as static but it's not read.
I'm using the simply render_template method:
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('index.html', nome=nome)
enter code here
The error message clearly states that the image could not be found.
Your code does not match the error message. One time you have .jgp as file ending, one time .jpg.jpg.
Try to compare the image name and path with the one you write in your code.
If you cannot figure out how to fix this, please also give us an overview of your directory structure.
i want that the serveur connect and send data to the python serveur but unfortunately i have this errorSCRIPT12029: SCRIPT12029: WebSocket Error: Network Error 12029, i have seen on this website Connecting to TCP Socket from browser using javascript at the second post when he says You can use also attempt to use HTML5 Web Sockets (Although this is not direct TCP communication):
so this is the java script html code
<!DOCTYPE html>
<html>
<head>
<title>JS #0</title>
</head>
<body>
<script>
try{
var connection = new WebSocket('ws://127.0.0.1:1555');
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
}catch(Exception){
}
</script>
</body>
</html>
python
# coding: utf-8
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
a=1
if(a==1):
try:
socket.bind(('', 1555))
socket.listen(5)
print("client start")
client, address = socket.accept()
print ("{} connected".format( address ))
response = client.recv(255)
if response != "":
print(response)
except Exception as e:
print(e)
finally:
socket.close()
Second try
#!/usr/bin/env python
# WS server that sends messages at random intervals
import asyncio
import datetime
import random
import websockets
async def time(websocket, path):
while True:
now = datetime.datetime.utcnow().isoformat() + "Z"
await websocket.send(now)
await asyncio.sleep(random.random() * 3)
start_server = websockets.serve(time, "127.0.0.1", 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
and the html code
<!DOCTYPE html>
<html>
<head>
<title>WebSocket demo</title>
</head>
<body>
<script>
var ws = new WebSocket("ws://127.0.0.1:5678/"),
messages = document.createElement('ul');
ws.onmessage = function (event) {
var messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode(event.data);
message.appendChild(content);
messages.appendChild(message);
};
document.body.appendChild(messages);
</script>
</body>
</html>
have i done wrong or it's not the right code, i have found the code on this website https://websockets.readthedocs.io/en/stable/intro.html
new photo of error with Microsoft edge.
configuration with about:flags
second post answer of the website give in the awnser
detecter automaticement le reseau intranet= automatically detect the intranet network
Not the world's best answer, but hopefully this will get you on track!
Browsers do not support raw sockets, but they do support one specific socket protocol, WebSockets. WebSockets are built on top of TCP/IP and are a great, easy way to form long-lived connections between a browser and another machine. Because your code was originally utilizing raw sockets, the browser was never going to perform a handshake. Now that you've changed your answer to support websockets, you're closer than ever!
I'm not sure what issue you're experiencing with your new code because it works perfectly for me. I made a few modifications since I am running a lot of dev environments and I can't have StackExchange debugging interfering. Here's my code which only has 3 changed lines from yours:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket demo</title>
</head>
<body>
<script>
var ws = new WebSocket('ws://127.0.0.1:5678/'),
messages = document.createElement('ul');
ws.onmessage = function(event) {
var messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode(event.data);
message.appendChild(content);
messages.appendChild(message);
};
document.body.appendChild(messages);
</script>
</body>
</html>
#!/usr/bin/env python3
# WS server example
import sys
# forcibly adding a path for the following libraries
# this is probably not necessary on anyone else's machine,
# but I need it just for testing this answer
sys.path.append('/usr/local/lib/python3.7/site-packages')
import asyncio
import websockets
import datetime
import random
async def time(websocket, path):
while True:
now = datetime.datetime.utcnow().isoformat() + "Z"
await websocket.send(now)
await asyncio.sleep(random.random() * 3)
start_server = websockets.serve(time, "127.0.0.1", 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
And it works great:
I saved your python script as foo.py and the html document as bar.html to my desktop. To start the python server, I ran python3 foo.py from the command line, and then I opened the html file using my preferred browser, no http servers were required for this example.
What errors are you seeing in the browser or console that are prohibiting this from working?
Error 12029 is the error OP is seeing! By default, Edge will not listen on local interfaces, e.g. localhost and 127.0.0.1. This thread on Microsoft.com has some troubleshooting advice for developers using Edge. Let us know if these configurations are helpful.
I'm new to Flask and a bit rusty on my Javascript. I have need to generate events in python externally and push them to a web page in realtime, so I've chosen Flask-SocketIO. I've built the simplest example that I can think of:
from flask_socketio import SocketIO, emit
from flask import Flask, render_template
from time import sleep
from threading import Thread, Event
app = Flask(__name__)
app.config['SECRET_KEY'] = 'haha!'
app.debug = True
socketio = SocketIO(app)
thread = Thread()
thread_stop_event = Event()
class MyThread(Thread):
def __init__(self):
super(MyThread, self).__init__()
def ticker(self):
print("ticking")
while not thread_stop_event.isSet():
text="hi there"
print(text)
socketio.emit('message', {'data': text})
sleep(1)
def run(self):
self.ticker()
#app.route('/')
def index():
return render_template('index.html')
#socketio.on('connect')
def test_connect():
global thread
print('Client connected')
if not thread.isAlive():
print("Starting Thread")
thread = MyThread()
thread.start()
#socketio.on('disconnect')
def test_disconnect():
print('Client disconnected')
if __name__ == '__main__':
socketio.run(app)
With this index.html file in a templates directory:
<html>
<head>
<title>Ticker</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
var socket = io.connect('http://127.0.0.1:5000');
socket.on('connect', function() {
socket.send('User has connected!');
});
socket.on('message', function(text) {
$("#messages").append('<li>'+text+'</li>');
console.log('Received message');
});
});
</script>
<ul id="messages"></ul>
</body>
</html>
I'm seeing a list of "hi there"s in the console, but nothing in the browser at localhost:5000. It seems to hang--the bottom of the browser says "Waiting for cache" or Waiting for localhost". Can someone figure out what I'm doing wrong? Many thanks in advance!
OK, I'm answering this for anyone who is coming across this need to have an external process sending messages to a browser using Flask and socketIO. I spent a lot of time Googling and Stackoverflowing, and I never found a really simple, clean example, so here it is to the best of my ability.
This is what I wanted: to use Python, Flask, and SocketIO and to have an external process running sending messages that would be shown in the browser. My first stab at it was what I wrote as a question, which was to spawn a thread with the external process. What I ended up doing was to have a different Python program be the external process, which for my application, a robotic sensor reporter, is actually better. So, mea culpa, I'm not answering my question exactly. But as I wrote, I hope that there's some utility in putting this answer here, because I never found a simple example of how to do that. Here it is.
I think that the essential problem is that you need some sort of load balancing to have an external process sending messages through socketio, as the code doesn't know if it's receiving messages from 1 program or 10,000. The easiest way it ultimately seemed to me to be was to use redis. So you need to have redis up and running when the code is running. On a Mac with Homebrew, you install redis with:
$ brew install redis
And you run it with
$ redis-server /usr/local/etc/redis.conf
(There are obviously ways to have it start at boot.) Here's my server code, main.py
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'slivovitz'
app.debug = True
socketio = SocketIO(app, message_queue='redis://')
#app.route("/")
def index():
return render_template("index.html")
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0')
Here's my external process code, broadcast.py
from flask_socketio import SocketIO
import datetime
import time
socketio = SocketIO(message_queue='redis://')
if __name__ == '__main__':
while True:
msg = datetime.datetime.now().strftime("%a, %d %b %Y %H:%M:%S")
print(msg)
socketio.emit('message', msg, broadcast=True)
time.sleep(1)
And here's the html code index.html in the templates directory:
<html>
<head>
<title>Listener</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
var socket = io.connect();
socket.on('message', function(msg) {
$("#messages").append('<li>'+msg+'</li>');
console.log('Received message');
});
});
</script>
<ul id="messages"></ul>
</body>
</html>
And if you're looking to do this whole shenanegan on a Raspberry Pi, install redis with https://www.alibabacloud.com/blog/how-to-install-and-configure-redis-server-on-debian-9_472211. It's just that crazy easy. Enjoy 😊
I'm trying to use Brython to run Python code in the browser, and to use websockets in that Python code.
I have working JavaScript code that can connect to the Websocket echo server at http://www.websocket.org/echo.html.
According to the documentation, the function JSObject can be used to manipulate JavaScript objects in Brython, but I can't get it to work using either ws = JSObject(WebSocket("ws://echo.websocket.org/")) or ws = JSObject(new WebSocket("ws://echo.websocket.org/")).
How can I make a simple "Hello World" example connecting to the echo server, in Python code, using Brython?
See also How to import library using Brython for using libraries that aren't built in to Brython (including the usual Python standard library).
Here is an example using the built-in websocket() function, included in py_websocket, and the server echo.websocket.org :
<html>
<head>
<meta charset="iso-8859-1">
<script src="/src/brython.js"></script>
<script type="text/python3">
def on_open():
# Web Socket is connected, send data using send()
data = doc["data"].value
if data:
ws.send(data)
alert("Message is sent")
def on_message(evt):
# message received from server
alert("Message received : %s" %evt.data)
def on_close(evt):
# websocket is closed
alert("Connection is closed")
ws = None
def _test():
global ws
# open a web socket
ws = websocket("wss://echo.websocket.org")
# attach functions to web sockets events
ws.on_open = on_open
ws.on_message = on_message
ws.on_close= on_close
def close_connection():
ws.close()
</script>
</head>
<body onload="brython(1)">
<input id="data">
<button onclick="_test()">Run WebSocket</button>
<p><button onclick="close_connection()">Close connection</button>
</body>
</html>
The code should be self-explanatory. The Brython site needs to be completed with more documentation about web sockets