I created a server with python.
Now I have a webpagecgi to screen my result and also a svg file.
I tested 3 ways to that:
Solution1 a javascript method to load quicky the svg (works out of server-> but not in the localserver)
Solution2 a simple object import (works out of server -> but not in the localserver)
Solution3 svg inside the html (works out and in the server)
I would like to use the solution 1 or 2 because the 3 is not comfortable and dirty for me...
Why Solution1 and 2 does not work? I think they do not find svg file but I don't understand why...
os.system("cp %s WEBSERVER/toto.svg"%(svg))
print 'Content-type: text/html' #application/xhtml+xml'# image/svg+xml'
print '''
<html>
<head>
<script language="javascript">
function loadSVG(id, svg) {
var element = document.getElementById(id);
var object = document.createElement("object");
object.type = "image/svg+xml";
object.data = svg;
element.appendChild(object);
}
</script>
</head>
<body>
SOLUTION1<br/>
<script type="text/javascript">
loadSVG('hca', 'WEBSERVER/toto.svg');
</script>
SOLUTION2<br/>
<object type='image/svg+xml' data ='WEBSERVER/toto.svg'></object>
SOLUTIONT3<br/>
<svg xmlns="http://www.w3.org/2000/svg"
width="800" height="800" >
<rect x="50" y="200" width="250" height="40" />
</svg>
</body>
</html>
'''
Here is the webserver that I launch in python:
#!/usr/bin/python
import BaseHTTPServer
import CGIHTTPServer
import cgitb; cgitb.enable()
server = BaseHTTPServer.HTTPServer
handler = CGIHTTPServer.CGIHTTPRequestHandler
server_address = ("0.0.0.0", 8123)
handler.cgi_directories = ['/WEBSERVER']
httpd = server(server_address, handler)
try:
print "Running HTTP server"
httpd.serve_forever()
except KeyboardInterrupt:
print "Server Stoped"
Related
Is it possible to have a user upload an arbitrary Python script (that uses built-ins only, no external packages) and then execute it using PyScript?
You can use an HTML <input> element to upload the file, and use await file.txt() to get the source. Then there are a couple ways to execute the code.
Using Python's exec() method:
<script defer src="https://pyscript.net/releases/2022.12.1/pyscript.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2022.12.1/pyscript.css">
<input type="file" id="file-upload">
<py-script>
import js
from pyodide.ffi.wrappers import add_event_listener
async def upload_and_run(event):
file_list = event.target.files
first_item = file_list.item(0)
src = await first_item.text()
exec(src)
input_elem = js.document.getElementById("file-upload")
add_event_listener(input_elem, "change", upload_and_run);
</py-script>
Or, if you want the script to behave like a <py-script> tag, with pretty error handling and such, you could add source to a new <py-script> tag:
<script defer src="https://pyscript.net/releases/2022.12.1/pyscript.js"></script>
<link rel="stylesheet" href="https://pyscript.net/releases/2022.12.1/pyscript.css">
<input type="file" id="file-upload">
<py-script>
import js
from pyodide.ffi.wrappers import add_event_listener
async def upload_as_script_tag(event):
file_list = event.target.files
first_item = file_list.item(0)
src = await first_item.text()
newTag = js.document.createElement("py-script")
newTag.innerText = src
js.document.body.appendChild(newTag)
input_elem = js.document.getElementById("file-upload")
add_event_listener(input_elem, "change", upload_as_script_tag);
</py-script>
</body>
I have a Rest API to execute curl command in bash script to retrieve newspaper information from a national library website as follows. I can run this bash script in two different ways:
$ bash sof.sh # input arguments are hardcoded! WORKS OK!
$ python file.py # input arguments are passed from a dictionary! ERROR!
Here is sof.sh file:
#!/bin/bash
: '
################## 1) Running via Bash Script & hardcoding input arguments ##################
myQUERY="Rusanen"
myORDERBY="DATE_DESC"
myFORMATS='["NEWSPAPER"]'
myFUZZY="false"
myPubPlace='["Iisalmi", "Kuopio"]'
myLANG='["FIN"]'
################## 1) Running via Bash Script & hardcoding input arguments ##################
# Result: OK! a json file with retreived expected information
'
#: '
################## 2) Running from python script with input arguments ##################
for ARGUMENT in "$#"
do
#echo "$ARGUMENT"
KEY=$(echo $ARGUMENT | cut -f1 -d=)
KEY_LENGTH=${#KEY}
VALUE="${ARGUMENT:$KEY_LENGTH+1}"
export "$KEY"="$VALUE"
done
echo $# "ARGS:" $*
################## 2) Running from python script with input arguments ##################
# Result: Error!!
#'
out_file_name="newspaper_info_query_${myQUERY// /_}.json"
echo ">> Running $0 | Searching for QUERY: $myQUERY | Saving in $out_file_name"
curl 'https://digi.kansalliskirjasto.fi/rest/binding-search/search/binding?offset=0&count=10000' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Pragma: no-cache' \
--compressed \
--output $out_file_name \
-d #- <<EOF
{ "query":"$myQUERY",
"languages":$myLANG,
"formats":$myFORMATS,
"orderBy":"$myORDERBY",
"fuzzy":$myFUZZY,
"publicationPlaces": $myPubPlace
}
EOF
Running $ bash sof.sh with manually hardcoded input arguments in the bash script works fine with expected behavior, i.e., it returns a json file with expected information.
However, to automate my code, I need to run this bash script using $ python file.py with subprocess as follows:
def rest_api_sof(params={}):
params = {'query': ["Rusanen"],
'publicationPlace': ["Iisalmi", "Kuopio"],
'lang': ["FIN"],
'orderBy': ["DATE_DESC"],
'formats': ["NEWSPAPER"],
}
print(f"REST API: {params}")
subprocess.call(['bash',
'sof.sh',
f'myFORMATS={params.get("formats", "")}',
f'myQUERY={",".join(params.get("query"))}',
f'myORDERBY={",".join(params.get("orderBy", ""))}',
f'myLANG={params.get("lang", "")}',
f'myPubPlace={params.get("publicationPlace", "")}',
])
if __name__ == '__main__':
rest_api_sof()
To replicate and see Error in json file, please comment 1) Running via Bash Script & hard coding input arguments and correspondingly uncomment 2) Running from python script with input arguments and run $ python file.py.
Here is the error in my json file after running $ python file.py:
<!doctype html>
<html lang="fi">
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
<title>Digitaaliset aineistot - Kansalliskirjasto</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="robots" content="index, follow"/>
<meta name="copyright" content="Kansalliskirjasto. Kaikki oikeudet pidätetään."/>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<base href="/">
<meta name="google-site-verification" content="fLK4q3SMlbeGTQl-tN32ENsBoaAaTlRd8sRbmTxlSBU" />
<meta name="msvalidate.01" content="7EDEBF53A1C81ABECE44A7A666D94950" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=Open+Sans:ital,wght#0,300;0,400;0,600;0,700;1,400&display=swap" rel="stylesheet">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-10360577-3', 'auto');
</script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-KF8NK1STFH"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
// see google-analytics.service
</script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
(function() {
var u = "https://tilasto.lib.helsinki.fi/";
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', '17']);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true;
g.src = u + 'matomo.js';
s.parentNode.insertBefore(g, s);
}
)();
</script>
<noscript><p><img src="https://tilasto.lib.helsinki.fi/matomo.php?idsite=17&rec=1" style="border:0;" alt=""/></p></noscript>
<!-- End Matomo Code --><style type="text/css">[ng-cloak] { display: none !important; }</style>
<script>
window.errorHandlerUrl = "/rest/js-error-handler";
window.commonOptions = {"localLoginEnabled":true,"localRegistrationEnabled":false,"marcOverlayEnabled":true,"opendataEnabled":true,"overrideHeader":"","hakaEnabled":true,"includeExternalResources":true,"legalDepositWorkstation":false,"jiraCollectorEnabled":true,"buildNumber":"8201672f226078f2cefbe8a0025dc03f5d98c25f","searchMaxResults":10000,"showExperimentalSearchFeatures":true,"bindingSearchMaxResults":1000,"excelDownloadEnabled":true,"giosgEnabled":true};
</script>
<style type="text/css">.external-resource-alt { display: none !important; }</style>
</head>
<body class="digiweb">
<noscript>
<h3>Sovellus vaatii JavaScriptin.</h3>
<p>Ole hyvä ja laita selaimesi JavaScript päälle, jos haluat käyttää palvelua.</p>
<h3>Aktivera Javascript.</h3>
<p>För att kunna använda våra webbaserade system behöver du ha Javascript aktiverat.</p>
<h3>This application requires JavaScript.</h3>
<p>Please turn on JavaScript in order to use the application.</p>
</noscript><app-digiweb></app-digiweb>
<div id="kk-server-error" style="display: none;">
<h1 align="center">Järjestelmässä tapahtui virhe.</h1></div>
<div id="kk-server-page" style="display: none;">
</div>
<script type="text/javascript">
window.language = "fi";
window.renderId = 1673541833124;
window.facebookAppId = "465149013631512"
window.reCaptchaSiteKey = "6Lf7xuASAAAAANNu9xcDirXyzjebiH4pPpkKVCKq";
</script>
<script src="/assets/runtime-es2015.f1ac93cb35b9635f0f7e.js" type="module"></script>
<script src="/assets/runtime-es5.f1ac93cb35b9635f0f7e.js" nomodule></script>
<script src="/assets/polyfills-es2015.8db02cde19c51f542c72.js" type="module"></script>
<script src="/assets/polyfills-es5.2273af7ef2cf66cdc0de.js" nomodule></script>
<script src="/assets/styles-es2015.a539381f703344410705.js" type="module"></script>
<script src="/assets/styles-es5.a539381f703344410705.js" nomodule></script>
<script src="" type="module"></script>
<script src="" type="module"></script>
<script src="" nomodule></script>
<script src="/assets/main-es2015.b5796f606e925a9d947d.js" type="module"></script>
<script src="/assets/main-es5.b5796f606e925a9d947d.js" nomodule></script>
</body>
</html>
To debug this, I replaced sof.sh with a very simple Bash script:
#!/bin/sh
printf "'%s'\n" "$#"
It outputs the following:
'myFORMATS=['NEWSPAPER']'
'myQUERY=Rusanen'
'myORDERBY=DATE_DESC'
'myLANG=['FIN']'
'myPubPlace=['Iisalmi', 'Kuopio']'
In case it's not obvious, the problem is that Python internally prefers single quotes around the strings in the lists; and so, it produces invalid JSON.
The simple fix is probably to force these values into JSON format so that you don't have to change the rest of the code.
import json
...
subprocess.call(['bash',
'sof.sh'] +
[x + "=" + json.dumps(params[x]) for x in params.keys()])
This produces lists of all the values because your params values are all lists. If you don't want the query and language to be lists (i.e. don't want square brackets around them), take away the square brackets around them in the definition of the params dict in the Python code.
I have recently come across the Pyodide project.
I have built a little demo using Pyodide, but although I've spent a lot of time looking at the source, it is not obvious (yet) to me how to redirect print output from python (other than modifying the CPython source), and also, how to redirect output from matplotlib.pyplot to the browser.
From the source code, FigureCanvasWasm does have a show() method with the appropriate backend for plotting to the browser canvas - however, it is not clear to me how to instantiate this class and invoke it's show() method or indeed, if there is another more obvious way of redirecting plots to canvas.
My questions therefore are:
How do I redirect print() messages
How do I force pyodide to plot matplotlib figures in the browser?
Here is my test page:
<!doctype html>
<meta charset="utf-8">
<html lang="en">
<html>
<head>
<title>Demo</title>
<script src="../../pyodide/build/pyodide.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
languagePluginLoader.then(() => {
pyodide.loadPackage(['matplotlib']).then(() => {
pyodide.runPython(`
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.ylabel('some numbers')
#fig = plt.gcf()
#fig.savefig(imgdata, format='png')
print('Done from python!')`
);
//var image = pyodide.pyimport('imgdata');
//console.log(image);
});});
</script>
<html>
First of all let's see if we can get just anything to show up in the browser; e.g. a normal string. Python variables are stored in the pyodide.globals attribute. Hence we can take the python object from there and place it into a <div> element on the page.
<!doctype html>
<meta charset="utf-8">
<html>
<head>
<title>Demo</title>
<script src="../pyodide/pyodide.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
languagePluginLoader.then(() => {
pyodide.runPython(`my_string = "This is a python string." `);
document.getElementById("textfield").innerText = pyodide.globals.my_string;
});
</script>
<div id="textfield"></div>
<html>
Now I guess we can do the same with a matplotlib figure. The following would show a saved png image in the document.
<!doctype html>
<meta charset="utf-8">
<html lang="en">
<html>
<head>
<title>Demo</title>
<script src="../pyodide/pyodide.js"></script>
</head>
<body>
</body>
<script type="text/javascript">
languagePluginLoader.then(() => {
pyodide.loadPackage(['matplotlib']).then(() => {
pyodide.runPython(`
import matplotlib.pyplot as plt
import io, base64
fig, ax = plt.subplots()
ax.plot([1,3,2])
buf = io.BytesIO()
fig.savefig(buf, format='png')
buf.seek(0)
img_str = 'data:image/png;base64,' + base64.b64encode(buf.read()).decode('UTF-8')`
);
document.getElementById("pyplotfigure").src=pyodide.globals.img_str
});});
</script>
<div id="textfield">A matplotlib figure:</div>
<div id="pyplotdiv"><img id="pyplotfigure"/></div>
<html>
I haven't looked into the backends.wasm_backend yet, so that may allow for a more automated way of the above.
When using the wasm backend, the canvas property of a figure is an instance of FigureCanvasWasm. Calling the show() method of the canvas should be sufficient to display the figure in the browser. Unfortunately a minor bug in the create_root_element() method of the canvas prevents the figure from being displayed. This method creates a div element that will contain the figure. It tries first to create an iodide output div element. If that fails a plain HTML div element is created. This element however is never appended to the document and remains therefore invisible.
Below are the lines of code from FigureCanvasWasm were it happens
def create_root_element(self):
# Designed to be overridden by subclasses for use in contexts other
# than iodide.
try:
from js import iodide
return iodide.output.element('div')
except ImportError:
return document.createElement('div')
The comment suggests the non-iodide code is a stub that needs to be extended, by overriding the method. This would require subclassing FigureCanvasWasm, installing it as a pyodide module and configuring matplotlib to use that backend.
There is a shortcut however, because python allows overriding a method of an instance, without modifying the class, as per question 394770. Putting the following code in your HTML document gives a figure in the browser
import numpy as np
from matplotlib import pyplot as plt
from js import document
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
f = plt.figure()
plt.plot(x,y)
# ordinary function to create a div
def create_root_element1(self):
div = document.createElement('div')
document.body.appendChild(div)
return div
#ordinary function to find an existing div
#you'll need to put a div with appropriate id somewhere in the document
def create_root_element2(self):
return document.getElementById('figure1')
#override create_root_element method of canvas by one of the functions above
f.canvas.create_root_element = create_root_element1.__get__(
create_root_element1, f.canvas.__class__)
f.canvas.show()
Initially the toolbar did not show icons. I had to download, unzip and install fontawesome alongside pyodide and include the following line in the header to get those
<link rel="stylesheet" href="font-awesome-4.7.0/css/font-awesome.min.css">
Edit:
About the first part of your question, redirecting the output stream to the browser, you could take a look at how it is done in pyodide's console.html.
It replaces sys.stdout by a StringIO object
pyodide.runPython(`
import sys
import io
sys.stdout = io.StringIO()
`);
Then run the python code (that can be completely oblivious to the fact that it is running in a wasm context)
pyodide.runPython(`
print("Hello, world!")
`);
Finally, send the contents of the stdout buffer to an output element
var stdout = pyodide.runPython("sys.stdout.getvalue()")
var div = document.createElement('div');
div.innerText = stdout;
document.body.appendChild(div);
To show print() calls form pyodide you can use the parameters on loadPyodide to redirect stdout:
var paragraph = document.getElementById("p");
pyodide = await loadPyodide({
indexURL : "https://cdn.jsdelivr.net/pyodide/v0.18.1/full/",
stdin: window.prompt,
stdout: (text) => {paragraph.textContent += text;},
stderr: (text) => {paragraph.textContent += text;}
});
https://github.com/pyodide/pyodide/blob/main/src/js/pyodide.js
I created a simple interactive shell for Python. Read my tutorial if you need more detailed information.
const output = document.getElementById("output")
const code = document.getElementById("code")
code.addEventListener("keydown", function (event) {
if (event.ctrlKey && event.key === "Enter") {
evaluatePython()
}
})
function addToOutput(s) {
output.value += `>>>${code.value}\n${s}\n`
output.scrollTop = output.scrollHeight
code.value=''
}
output.value = 'Initializing...\n'
// init pyodide
languagePluginLoader.then(() => { output.value += 'Ready!\n' })
function evaluatePython() {
pyodide.runPythonAsync(code.value)
.then(output => addToOutput(output))
.catch((err) => { addToOutput(err) })
}
<!DOCTYPE html>
<head>
<script type="text/javascript">
// this variable should be changed if you load pyodide from different source
window.languagePluginUrl = 'https://pyodide-cdn2.iodide.io/v0.15.0/full/';
</script>
<script src="https://pyodide-cdn2.iodide.io/v0.15.0/full/pyodide.js"></script>
</head>
<body>
Output:
</div>
<textarea id='output' style='width: 100%;' rows='10' disabled></textarea>
<textarea id='code' value='' rows='2'></textarea>
<button id='run' onclick='evaluatePython()'>Run</button>
<p>You can execute any Python code. Just enter something in the box above and click the button (or Ctrl+Enter).</p>
<div><a href='https://github.com/karray/truepyxel/demo.html'>Source code</a></div>
</body>
</html>
Here is the example for matplotlib. Note that this will load a bunch of dependencies which will take up to several minutes.
let python_code = `
from js import document
import numpy as np
import scipy.stats as stats
import matplotlib.pyplot as plt
import io, base64
def generate_plot_img():
# get values from inputs
mu = int(document.getElementById('mu').value)
sigma = int(document.getElementById('sigma').value)
# generate an interval
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
# calculate PDF for each value in the x given mu and sigma and plot a line
plt.plot(x, stats.norm.pdf(x, mu, sigma))
# create buffer for an image
buf = io.BytesIO()
# copy the plot into the buffer
plt.savefig(buf, format='png')
buf.seek(0)
# encode the image as Base64 string
img_str = 'data:image/png;base64,' + base64.b64encode(buf.read()).decode('UTF-8')
# show the image
img_tag = document.getElementById('fig')
img_tag.src = img_str
buf.close()
`
languagePluginLoader.then(()=>pyodide.runPythonAsync(python_code).then(()=>document.getElementById('status').innerHTML='Done!'))
<!DOCTYPE html>
<head>
<script type="text/javascript">
// this variable should be changed if you load pyodide from different source
window.languagePluginUrl = 'https://pyodide-cdn2.iodide.io/v0.15.0/full/';
</script>
<script src="https://pyodide-cdn2.iodide.io/v0.15.0/full/pyodide.js"></script>
</head>
<body>
Status: <strong id='status'>Initializing...</strong>
<br><br>
mu:
<input id='mu' value='1' type="number">
<br><br>
sigma:
<input id='sigma' value='1' type="number">
<br><br>
<button onclick='pyodide.globals.generate_plot_img()'>Plot</button>
<br>
<img id="fig" />
</body>
</html>
I have read many other answers here, but find that following them doesn't still work for me.
What I want is for one python script which runs Flask to get a value submitted from an html form, and then pass it into an argument for a second python script that is triggered from the first python script.
My python Flask code is as below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Webapp.py
from flask import Flask, render_template, request
import datetime
import os
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/')
def my_form():
return render_template("my-form.html")
#app.route('/', methods=['POST'])
def my_form_post():
text = request.form['field1']
mid = text.upper()
now = datetime.datetime.now()
timeString = now.strftime("%d-%m-%Y %H:%M:%S")
IDData = {
'title' : mid,
'time': timeString
}
print('ID is: {0}'.format(mid))
os.system("sudo python /home/pi/Add/triggertest.py mid")
return render_template('cp.html', **IDData)
if __name__ == "__main__":
try:
app.run(host='0.0.0.0', port=80, debug=True)
except KeyboardInterrupt:
logfile.close()
My html for index file is as below:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>HEAT</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href='/static/style.css' />
</head>
<body>
<img src="/logo.png" alt="LOGO" style="width:168px;height:56px;">
<h1>"HEAT"</h1>
<div id="time">
<h3>The current date and time on the server is: {{ time }}</h3>
</div>
<!--
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function autoRefresh_div()
{
$("#time").load("cp.html");// a function which will load data from other file after x seconds
}
setInterval('autoRefresh_div()', 0500); // refresh div after 0.5 secs
</script>
-->
<form action="" method="POST">
<ul class="form-style-1">
<li><label>Melt ID <span class="required">*</span></label></li>
<li>
<input type="text" name="field1" class="field-divided" placeholder="Please enter the meltID here"/>
</li>
<li>
<input type="submit" name="my-form" value="Submit" />
</li>
</ul>
</form>
</body>
</html>
My cp.html is as below:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Control Panel</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href='/static/style.css' />
</head>
<body>
<div id="time">
<!--
<code>
#app.route('/my-form', methods=['POST'])
def my_form_post():
text = request.form['field1']
processed_text = text.upper()
now = datetime.datetime.now()
timeString = now.strftime("%d-%m-%Y %H:%M:%S")
IDData = {
'title' : processed_text,
'time': timeString
}
return render_template('cp.html', **IDData)</code>-->
<h3>The melt ID is: {{ IDData }}</h3>
</div>
</body>
</html>
My code for second python script triggertest.py is:
# -*- coding: utf-8 -*-
#!/usr/bin/python
# For logging debug output:
#import logging
#logging.basicConfig(level=logging.DEBUG)
import time
import os
import sys
import Adafruit_GPIO.SPI as SPI
import Adafruit_MAX31855.MAX31855 as MAX31855
from datetime import datetime
# Define a function to convert celsius to fahrenheit.
def c_to_f(c):
return c * 9.0 / 5.0 + 32.0
# Raspberry Pi software SPI configuration.
#CLK = 25
#CS = 24
#DO = 18
#sensor = MAX31855.MAX31855(CLK, CS, DO)
# Raspberry Pi hardware SPI configuration.
SPI_PORT = 0
SPI_DEVICE = 0
sensor = MAX31855.MAX31855(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
def write_temp(t, logfile):
#Writes temperature as .3 float to open file handle.
logfile.write('{},{:.3f}\n'.format(datetime.now().strftime('%d-%m-%Y %H:%M:%S'), t))
def loop(t, logfile):
#Starts temperature logging until user interrupts.
while True:
#temp = sensor.readTempC()
t = sensor.readTempC()
if t:
write_temp(t, logfile)
#print('Current temperature: {0:.3f} °C'.format(t))
sys.stdout.flush() #Flush. Btw, print is time-consuming
time.sleep(.25)
# Instructions for exiting the program
print('Trigger testing in progress. Press Ctrl-C to quit.')
if __name__ == '__main__':
# The next two lines are for using DS18B20 temperature sensor
# Take the first match for a device that is not 'w1_bus_master1'
#dev = [d for d in os.listdir('/sys/bus/w1/devices') if d != 'w1_bus_master1'][0]
# Prepare the log filename
fname = str(sys.argv[1]) + "-" + datetime.now().strftime("%d-%m-%Y-%H-%M-%S")+".csv"
# Immediately open the log in append mode and do not close it
logfile = open(fname, 'a')
try:
# Only pass device and file handle, not the file name.
t = sensor.readTempC()
internal = sensor.readInternalC()
loop(t, logfile)
print('Thermocouple Temperature: {0:0.3F}*C / {1:0.3F}*F'.format(t, c_to_f(temp)))
print(' Internal Temperature: {0:0.3F}*C / {1:0.3F}*F'.format(internal, c_to_f(internal)))
#time.sleep(1.0)
except KeyboardInterrupt:
# Close log file on exit
logfile.close()
My problems are:
Script #2 (triggertest.py which logs temperature) is starting, but it is not logging anything. I guess because the argument is not being passed?
I can end script #2 with Ctrl-C, but script #1 with flask remains running, which makes me need to restart the raspberry pi to run/test everything again.
Any ideas?
P.S. I have put 4 codes here making this file too long, and I apologize for that. I am a newbie to HTML and Python, and hence stuck here.
I am trying to put a simple python script (here I've used a random two-word generator which works fine) in a div on a webpage with Ajax and have a button beneath that reloads it. The page successfully loads the script... however, I haven't quite got my head around the missing part to call the script again to reload the random two words made by the python script (I understand why the code below is wrong but I can't work out how to make it right!). Pointer much appreciated!
(N.B. Yes I am using Python 2.4 because my web host hasn't upgraded yet - they will soon! And yes I saw this question but it didn't work for me...)
HTML:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<title>Find a sentence</title>
<script src="http://code.jquery.com/jquery-2.0.3.js"></script>
<script>
$(function()
{
$.ajax({
url: "cgi-bin/test.py",
type: "GET",
data: {foo: 'bar', bar: 'foo'},
success: function(response){
$("#div").html(response);
}
});
});
</script>
</head>
<body>
<div id="div"></div>
<form name="input" action="cgi-bin/test.py" method="get">
<input type="submit" value="Regenerate!">
</form>
</body>
PYTHON:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# enable debugging
import cgitb
cgitb.enable()
import linecache
from random import randrange
print "Content-Type: text/html"
print
# file length counter
def file_len(fname):
f = open(fname)
try:
for i, l in enumerate(f):
pass
finally:
f.close()
return i + 1
# range sizes
one_size = file_len('text/one.csv')
two_size = file_len('text/two.csv')
# random lines
one_line = randrange(one_size) + 1
two_line = randrange(two_size) + 1
# outputs
one_out = linecache.getline('text/one.csv', one_line)
two_out = linecache.getline('text/two.csv', two_line)
# output
sentence = one_out.strip('\n') + " " + two_out.strip('\n') + " "
print sentence
Well, I would assume that one has to click on the "Regenerate" button for the form to reload. My idea would be to have the ajax logic in a separate function. I don't think you need the form there since your reload call is now ajax call.
<head>
<script>
function reload() {
$.ajax({
url: "cgi-bin/test.py",
type: "GET",
data: {foo: 'bar', bar: 'foo'},
dataType : "html",
success: function(response){
$("#div").html(response);
}
});
}
$(window).load(function() {
reload();
$("#reload_button").click(function() {
reload();
});
});
</script>
</head>
<body>
<div id="div"></div>
<input type="button" id="reload_button" value="Regenerate!">
</body>