使用PyScript实现CSV上传读取时遇document未定义错误求助
解决PyScript中document未定义及CSV文件读取问题
问题场景
开发网页实现用户上传CSV文件,通过PyScript调用Python读取文件内容并转为列表打印,但运行时出现NameError: name 'document' is not defined错误。
原代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css"/> <script defer src="https://pyscript.net/latest/pyscript.js"></script> </head> <body> <py-config> packages = ["pandas"] </py-config> <div class="row overflow-hidden" id="content"> <div class="col mh-100 float-left" id="main"> <div id="fileinput"></div> <input type="file" name="upload" id="upload"> </div> </div> <py-script> import pandas as pd # Replace 'your_file.csv' with the path to your CSV file csv_file = document.getElementById('upload').files # Read the CSV file into a Pandas DataFrame df = pd.read_csv(csv_file) # Convert each row to a list and store them in an array rows_array = df.values.tolist() # Now, 'rows_array' contains each row of the CSV file as a list print(rows_array) </py-script> </body> </html>
报错信息:
Traceback (most recent call last): File "/home/pyodide/pyscript/_internal.py", line 104, in run_pyscript result = eval_code(code, globals=__main__.__dict__) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/_pyodide/_base.py", line 468, in eval_code .run(globals, locals) ^^^^^^^^^^^^^^^^^^^^ File "/lib/python311.zip/_pyodide/_base.py", line 310, in run coroutine = eval(self.code, globals, locals) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "<exec>", line 4, in <module> NameError: name 'document' is not defined
解决步骤
1. 导入document对象
PyScript中不能直接使用浏览器的document对象,需要从js模块显式导入:
from js import document
2. 监听文件上传事件
原代码在页面加载时就尝试获取文件,但此时用户还未选择文件,需要绑定change事件,当用户选择文件后再执行读取逻辑。
3. 正确处理File对象
files返回的是FileList,需要取第一个文件;同时pandas无法直接读取浏览器的File对象,需要将其转为Python的BytesIO对象。
修正后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSV Upload Reader</title> <link rel="stylesheet" href="https://pyscript.net/latest/pyscript.css"/> <script defer src="https://pyscript.net/latest/pyscript.js"></script> </head> <body> <py-config> packages = ["pandas"] </py-config> <div class="row overflow-hidden" id="content"> <div class="col mh-100 float-left" id="main"> <div id="fileinput"></div> <input type="file" name="upload" id="upload" accept=".csv"> </div> </div> <py-script> import pandas as pd from js import document from io import BytesIO def handle_file_upload(event): # 获取选中的第一个文件 file = document.getElementById('upload').files[0] # 将File对象转为ArrayBuffer,再转为BytesIO array_buffer = file.arrayBuffer() bytes_data = array_buffer.to_bytes() csv_file = BytesIO(bytes_data) # 读取CSV并转为列表 df = pd.read_csv(csv_file) rows_array = df.values.tolist() print(rows_array) # 绑定文件上传的change事件 document.getElementById('upload').addEventListener('change', handle_file_upload) </py-script> </body> </html>
关键说明
- 添加了
accept=".csv"限制文件选择仅为CSV,提升用户体验 - 使用
addEventListener绑定change事件,确保只有用户选择文件后才执行读取逻辑 - 通过
arrayBuffer()和BytesIO完成浏览器File对象到Python可读取对象的转换
内容的提问来源于stack exchange,提问作者rayyan
相关产品推荐
相关产品推荐

