This question already has answers here:
How to copy / download file created in Pyodide in browser?
(2 answers)
Closed 9 months ago.
I am doing a project with an html, js and css front-end and a python back-end.
I linked back-end and front-end with the py-script library.
I have to open a json file with the python script and it works, the problem is that it doesn't open the file where i want... it stores the file in this directory: /home/pyodide/file.json
How can I select the location where the file opens/gets created?
by the way, the code I am working with is this:
python
open("my_file.json")
# and it doesn't open it in the same directory as the python file who created it
The file /home/pyodide/file.json is located within the browser virtual file system. That file system is not part of your local disk storage. The virtual file system is not persistent. When you refresh the page any files stored are lost.
There is a set of FS APIs that manage the virtual file system which includes the ability to mount an IDBFS virtual file system for persistent storage. However, that is not the feature you are looking for.
Python applications have the same restrictions that JavaScript applies have. Neither can directly access the local file system. Applications must request access from the web browser and read data from the web browser. This is performed using HTML INPUT elements. The actual file access is performed by the FileRead class.
[UPDATE] Tonight I published an article on Pyscript Files and File Systems that explains in more detail with several examples.
This example is available on my website to experiment with: File Example
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
<title>File Example</title>
</head>
<body>
<p>This example shows how to read a file from the local file system and display its contents</p>
<br />
<p>Warning: Not every file type will display. PyScript removes content with tags such as XML, HTML, PHP, etc. Normal text files will work.</p>
<br />
<p>No content type checking is performed to detect images, executables, etc.</p>
<br />
<label for="myfile">Select a file:</label>
<input type="file" id="myfile" name="myfile">
<br />
<br />
<div id="print_output"></div>
<br />
<p>File Content:</p>
<div style="border:2px inset #AAA;cursor:text;height:120px;overflow:auto;width:600px; resize:both">
<div id="content">
</div>
</div>
<py-script output="print_output">
import asyncio
from js import document, FileReader
from pyodide import create_proxy
async def process_file(event):
fileList = event.target.files.to_py()
for f in fileList:
data = await f.text()
document.getElementById("content").innerHTML = data
def main():
# Create a Python proxy for the callback function
# process_file() is your function to process events from FileReader
file_event = create_proxy(process_file)
# Set the listener to the callback
e = document.getElementById("myfile")
e.addEventListener("change", file_event, False)
main()
</py-script>
</body>
</html>
Related
knowing that with <py-config> and <py-script> can execute python code in html
However, importing own function facing error
(PY1001): Unable to install package(s) 'bread'. Reason: Can't find a pure Python 3 Wheel for package(s) 'bread'. See: https://pyodide.org/en/stable/usage/faq.html#micropip-can-t-find-a-pure-python-wheel for more information.
html script
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<b><p>title <u><label id="AAA"></label></u> </p></b>
<br>
<py-config>
packages = ["bread"]
</py-config>
<py-script>
import bread.py
bread.fun_1()
</py-script>
</body>
</html>
own python script "bread.py"
def fun_1():
print("this is bread")
(pic) the result screenshot for above code
if I import my own function in another .py script is working, but do the same thing into html not works
(pic) the result that import my own function in another .py script is fine
I read through the link system recommend link, and link but I can't find out the solution myself, that I need a hand for this problem, thanks
The reason you are getting the error is that PyScript thinks you want to import a third-party package.
To import your custom modules, use [[fetch]] in your <py-config> and replace packages with files.
<py-config>
[[fetch]]
files = ["./bread.py"]
</py-config>
follow by discussion Get output of python script from within python script
I create online webpage (.html) run other .py script result, but face model not found error
logically seems the python code is fine, might the setting error or other issue I don't come up myself
printbob.py
#!/usr/bin/env python
import sys
def main(args):
for arg in args:
print(arg)
if __name__ == '__main__':
main(sys.argv)
test_0109_003.html
<html>
<head>
<link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css" />
<script defer src="https://pyscript.net/latest/pyscript.js"></script>
</head>
<body>
<b><p>title test 1.10-test_get_ print </p></b>
<br>
<py-script>
import printbob
printbob.main('arg1 arg2 arg3 arg4'.split(' '))
</py-script>
</body>
</html>
(pic 01) the result website showing
(pic 02) I put .py and .html script in WinSCP, online host system
so how to solve this problem, I locate that there might be the resaon
my winscp ip port is private that public cannot access to private's file, I'm not sure if this the reason, and if so, how to deal with it?
I've got a plotly visualization ('viz.html') in a html format. I've embedded it in my webpage using Flask's url_for() syntax, referencing the static folder:
<iframe id="igraph" scrolling="no" style="border:none;" seamless="seamless" src="{{ url_for('static', filename='viz.html') }}" height="400" width="120%"></iframe>
It deploys with no issues. However, my 'viz.html' will be rewritten frequently, updating itself with new data points. The updated visualization won't show with a control + R or webpage refresh. If I press control + F5 and do a cache refresh, then updated visualization will show.
I want users to be able to see the updated visualization without having to manually refresh the cache. So far I've tried:
Reloading flask app when file changes are detected in 'static' folder (Reload Flask app when template file changes)
check_folder = './static'
check_files = []
for dirname, dirs, files in os.walk(check_folder):
for filename in files:
filename = os.path.join(check_folder, filename)
check_files += [filename]
app.run(debug = True, extra_files = check_files)
Disabling browser cacheing on html page (http://cristian.sulea.net/blog/disable-browser-caching-with-meta-html-tags)
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
Disabling Python on Flask Cacheing
resp.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
resp.headers["Pragma"] = "no-cache"
resp.headers["Expires"] = "0"
Would like to know, is what I'm trying to do even possible?
If it's possible how can I go about doing it? Advice appreciated!
I am not a web developer but I worked with a few closely for 3 years. As far as I know, there is no way to control what other browsers saved as cache. If my browser has a version saved in the cache, it will use that one. Usually, browsers will check if all the files are updated, and eventually, it will refresh for everyone. I actually heard developers being asked "why didn't you fix what I told you?" and they were like, "I have, just hard refresh." So I don't think there is a way. IDK if anything new is out there.
I figured it out!
Instead of writing the plotly fig to a viz.html file, do viz = Markup(fig) in flask:
#app.route("/index/",methods=["POST", "GET"])
def foo():
from flask import Markup
# include_plotlyjs = True builds in the js library
# output_type = 'div' outputs the html code
viz = plot(fig, include_plotlyjs = True, output_type = 'div')
# Markup directly renders the html code
viz = Markup(viz)
return render_template('foo.html', viz = viz)
In foo.html, you can directly use viz as so:
<html>
<body>
viz
</body>
<html>
viola!
Is it possible to have a upload box on a site where a user can drag in a folder of files but instead of the entire folder being uploaded you can just grab the file names and metadata?
Not complete, but probably a good start...
This would be possible with dropzone.js, by setting the autoProcessQueue option to false. Then you can drop files/folders via the GUI, without them actually uploading, but still access the file object in javascript to get the metadata.
See this answer for more information on how to add a manual button to eventually start processing this queue if you wish. Regardless of whether you process that queue or not, you can use the addedfile event to manually inspect the file objects.
A really basic example, with the scripts loaded from a CDN, would look like:
<html>
<head>
<title> Dropzone</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/dropzone.css" integrity="sha256-0Z6mOrdLEtgqvj7tidYQnCYWG3G2GAIpatAWKhDx+VM=" crossorigin="anonymous" />
</head>
<body>
<div>
<form method='POST'
enctype="multipart/form-data"
class="dropzone"
id="my-awesome-dropzone"></form>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.0/dropzone.js" integrity="sha256-NLit4Z57jz8npRHkopjfr68hSZY1x/ruN0T8kf68xq4=" crossorigin="anonymous"></script>
<script type='text/javascript'>
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone("form#my-awesome-dropzone",
{ url: "/upload",
autoProcessQueue: false,
});
myDropzone.on("addedfile", function(file) {
// runs for every file dropped
console.log(file.name, file.fullPath, file.lastModified, file.size);
});
</script>
</body>
</html>
Dropping a single file with the above code outputs something like:
views.py undefined 1567770276854 1604
You can drop an entire folder, and every file recursively will appear, including file.fullPath for each:
models.py stack/models.py 1566159281216 1974
serializers.py stack/serializers.py 1565978398499 309
...
You could instead console.log(file) to inspect that object further (in your browser's dev tools console) to see the other available metadata.
To get this data to the backend you could use the fetch API or a similar AJAX post function. You may wish to add all the info to an array, then post this to the backend at once using another event handler tied to an "Upload metadata!" button.
I have created a test form which will ask users to enter a name and upload the image file:
<html lang="en">
<head>
<title>Testing image upload</title>
</head>
<body>
<form action="/services/upload" method="POST" enctype="multipart/form-data">
File Description: <input name='fdesc' type='text'><br>
File name: <input type="file" name="fname"><br>
<div><input type="submit"></div>
</form>
</body>
</html>
i need to get the file uploaded by the user and store it on my local PC. can this be done in python ? please let me know.
mod_python includes the FieldStorage class which allows you access to uploaded form data. In order to use it, you'd put something like the following in your Python script:
req.form = FieldStorage(req)
description = req.form['fdesc']
Since fdesc is a text input, description will be a string (more precisely, a StringField, which you can treat as a string).
file_field = req.form['fname']
Since fname is a file input, file_field will not be a string (or StringField), but rather a Field object which allows you access to the file data. The attribute file_field.file is a file-like object which you can use to read the file's contents, for example like so:
for line in file_field.file:
# process the line
You could use this to copy the file's data somewhere of your choosing, for example.
file_field.filename is the name of the file as provided by the client. Other useful attributes are listed in the documentation I linked to.
Maybie the minimal http cgi upload recipe and it's comments are helpful for you.
Hey David i got it working, i did it this way:
filename = request.FILES['fname']
destination = open('%s/%s'%(/tmp/,fileName), 'wb+')
for chunk in filename.chunks():
destination.write(chunk)
destination.close()
file = open('%s/%s'%(/tmp/,fileName),"rb").read()
Thanks for the help guys.