所以我在学习 google colab 时遇到了一个问题,在 google colab 中运行我的代码,我打开服务器并使用 IFRAME 查看我的网站,我试图解决的问题是选择 json 文件并单击上传时我希望该文件上传到我的笔记本本地内存,我的index.html文件有一个回调函数:
<script>
function uploadJson() {
google.colab.kernel.invokeFunction('notebook.uploadJSON', [file.name, content], {})
...
....
在colab本身中,我已经注册了该函数:
output.register_callback('notebook.uploadJSON', upload_json)
它位于该函数下:
def upload_json(filename, content): ...
我在控制台中遇到的问题是google 未定义,基本上回调不起作用。
我读到回调在使用 iframe 等时可能会遇到问题,有人知道原因或如何修复它吗?我还尝试在不使用 iframe 的情况下从 colab 中的单元格注入这些函数,这有点工作,但后来我遇到了 css 和 js 文件不工作的其他问题
from google.colab import output
import IPython
from IPython.display import display, IFrame
import json
import os
import requests
import time
def upload_json(filename, content):
data = json.loads(content)
filepath = os.path.join(os.getcwd(), filename)
with open(filepath, 'w') as f:
json.dump(data, f, indent=2)
print(f"File '{filename}' has been saved successfully in the Colab folder.")
if isinstance(data, dict):
first_key = next(iter(data))
print(f"First item in the JSON: {first_key}: {data[first_key]}")
elif isinstance(data, list) and len(data) > 0:
print(f"First item in the JSON: {data[0]}")
else:
print("The JSON file is empty or has an unexpected structure.")
output.register_callback('notebook.uploadJSON', upload_json)
# Function to download files from Firebase Storage
def download_file_from_firebase(bucket_name, file_name, local_path):
url = f'https://firebasestorage.googleapis.com/v0/b/{bucket_name}/o/{file_name}?alt=media'
response = requests.get(url)
if response.status_code == 200:
with open(local_path, 'wb') as file:
file.write(response.content)
print(f'File {file_name} downloaded to {local_path}.')
else:
print(f'Failed to download {file_name}. Status code: {response.status_code}')
# Download necessary files
bucket_name = 'KEY.com'
file_names = [
'index.html',
'TeamGraph.html',
'glossary.html',
'notifications.html',
'style.css',
'KEY.json',
'app.js',
'notifications.js'
]
for file_name in file_names:
download_file_from_firebase(bucket_name, file_name, file_name)
# List downloaded files
print("Downloaded files:", os.listdir())
# Serve the downloaded HTML files from Colab
time.sleep(2)
os.chdir('/content')
get_ipython().system_raw('python3 -m http.server 8000 &')
# Get the server URL
server_url = output.eval_js("google.colab.kernel.proxyPort(8000)")
# Function to display an HTML file in an iframe
def display_html(filename):
display(IFrame(src=f"{server_url}/{filename}", width='100%', height='600px'))
# Display the initial HTML file
display_html('index.html')
,这就是我的 index.html 中的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON Upload</title>
<link rel="stylesheet" href="style.css">
<script src="https://apis.google.com/js/platform.js"></script>
</head>
<body>
<div class="button-container">
<a href="index.html" class="nav-button" id="btnIndex">JSON Upload</a>
<a href="glossary.html" class="nav-button" id="btnGlossary">Glossary</a>
<a href="TeamGraph.html" class="nav-button" id="btnTeamGraph">Team Stats</a>
<a href="notifications.html" class="nav-button" id="btnNotifications">Notifications</a>
</div>
<div class="container">
<h2>Upload JSON File</h2>
<form id="jsonUploadForm">
<input type="file" id="fileInput" accept=".json">
<button type="button" id="uploadButton" onclick="uploadJson()">Upload</button>
</form>
</div>
<script>
function uploadJson() {
console.log("uploadJson function called"); // Debugging statement
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(event) {
const content = event.target.result;
console.log("File content:", content); // Debugging statement
google.colab.kernel.invokeFunction('notebook.uploadJSON', [file.name, content], {})
.then(response => {
console.log('Upload successful:', response);
alert('Upload successful');
})
.catch(error => {
console.error('Invoke function error:', error);
alert('Invoke function error: ' + error);
});
};
reader.onerror = function(event) {
console.error("Error reading file:", event.target.error);
alert("Error reading file: " + event.target.error);
};
reader.readAsText(file);
} else {
alert('No file selected');
}
}
// Disable the button for the current page
const currentPage = window.location.pathname.split("/").pop();
document.querySelector(`a[href="${currentPage}"]`).classList.add('active');
document.querySelector(`a[href="${currentPage}"]`).disabled = true;
</script>
</body>
</html>
绝对说对了,在 iframe 和 Google Colab 之间进行通信时会出现问题,尤其是在涉及
google.colab
对象时。这是因为在的 iframe 中运行的网页和的 Colab 笔记本本身在不同的 JavaScript 上下文中运行。
以下是解决此问题并使的 JSON 上传功能正常工作的分步指南:
1. 使用
postMessage
进行跨域消息传递
-
在 Colab 笔记本中(Python 代码):
```python from google.colab import output import json import os
def upload_json(filename, content): data = json.loads(content) filepath = os.path.join(os.getcwd(), filename) with open(filepath, 'w') as f: json.dump(data, f, indent=2) print(f"文件 '{filename}' 已成功保存在 Colab 文件夹中。")
output.register_callback('notebook.uploadJSON', upload_json)
# 添加消息处理程序 def handle_message(message): if message['data']['type'] == 'UPLOAD_JSON': upload_json(message['data']['filename'], message['data']['content'])
output.register_callback('notebook.handleMessage', handle_message) ```
-
在的
index.html
文件中(JavaScript):```javascript <script> function uploadJson() { const fileInput = document.getElementById('fileInput'); const file = fileInput.files[0];
if (file) { const reader = new FileReader(); reader.onload = function(event) { const content = event.target.result; // 向父窗口(Colab 笔记本)发送消息 parent.postMessage({ type: 'UPLOAD_JSON', filename: file.name, content: content }, '*'); // '*' 表示可以将消息发送到任何来源 }; reader.onerror = function(event) { console.error("读取文件时出错:", event.target.error); }; reader.readAsText(file); } else { alert('未选择文件'); }
} </script> ```
2. 使 Colab 环境可访问
需要确保的 iframe 代码可以访问
parent
对象。如果在不同的域或子域中提供
index.html
,请将
*
替换为 iframe 源的特定来源。
说明:
-
postMessage
: 这是在窗口或 iframe 之间进行通信的标准方法。父窗口(的 Colab 笔记本)侦听消息,iframe(的index.html
)发送消息。 -
消息处理程序: 在 Colab 中,
output.register_callback('notebook.handleMessage', handle_message)
设置一个侦听传入消息的处理程序。当接收到类型为'UPLOAD_JSON'
的消息时,它会调用upload_json
函数。 -
消息结构: 我们发送的消息有一个
type
字段(用于标识消息目的)以及filename
和content
。
其他提示:
-
调试: 在 Colab 笔记本和 iframe 的 JavaScript 代码中使用
console.log
语句来检查消息是否已正确发送和接收。 -
错误处理: 实现稳健的错误处理,以便在出现问题时通知用户。
通过进行这些更改,就可以从 iframe 中的 JavaScript 代码上传 JSON 文件,并让的 Colab 笔记本接收和处理该文件。
标签:javascript,python,iframe,callback,google-colaboratory From: 78786576