所以我使用的是Jupyter 4.x和python 3.5,试图“上传”一个.csv
,但实际上只是想把它作为一个字符串捕获然后使用setTimeout(function(){IPython.notebook.kernel.execute("stringData=StringIO(+"fr.result")");},5000);
为FileReader()
对象留出时间来完成二进制字符串转换,然后将字符串保存到python变量中。我测试了Filereader()
是通过在控制台中打印整个.csv
文件来工作的。但是出于某种原因,stringData在python端保持未定义。这是javascript单元格:
%%HTML
<input type="file" id="CSVFileInput" onchange="handleFiles(this.files)" value="upload csv">
<script>
var inputElement=document.getElementById('CSVFileInput');
function handleFiles() {
var file = inputElement.files[0];
var fr = new FileReader();
fr.readAsText(file);
var outputString=fr.result;
var command = "dataString ='"+outputString+"'";
setTimeout(function(){
IPython.notebook.kernel.execute(command);}
,5000);
}
inputElement.addEventListener("change", handleFiles, false);
</script>
在下一个单元格中,我测试输出并得到NameError
,因为dataString
未定义,这是下一个单元格:
dataString
另外,我是javascript的新手,但我想我应该重置超时?欢迎任何和所有的建议,我只觉得这是简单的方法。 PLS?当然,非常感谢!
FileReader
方法是异步的,因此在您尝试将outputString
设置为结果时没有加载数据。
处理此问题的正确方法是使用load
事件处理程序,因此您可以将代码修改为以下内容,而不是使用setTimeout()
(对于异步处理而言不可靠)。
function handleFiles() {
var file = this.files[0]; // "this" is the calling element
var fr = new FileReader();
fr.onload = function() {
var outputString = this.result; // here the data is ready. Now "this" = fr
var command = "dataString ='" + outputString + "'";
IPython.notebook.kernel.execute(command);
};
fr.readAsText(file); // invoked asynchronously
}
同时删除HTML中的内联JavaScript:
<input type="file" id="CSVFileInput" onchange="handleFiles(this.files)" value="upload csv">
至
<input type="file" id="CSVFileInput" title="upload csv">
(输入是value
时,type=file
无效,请改用title
)。然后使用以下代码来处理事件处理(在DOM加载之后):
document.getElementById("CSVFileInput").addEventListener("change", handleFiles);
function handleFiles() {
var file = this.files[0]; // "this" is the calling element
var fr = new FileReader();
fr.onload = function() {
var outputString = this.result; // here the data is ready. Now "this" = fr
var command = "dataString ='" + outputString + "'";
//IPython.notebook.kernel.execute(command);
console.log("Loaded file. Command:", command);
};
fr.readAsText(file); // invoked asynchronously
}
document.getElementById("CSVFileInput").addEventListener("change", handleFiles);
<input type="file" id="CSVFileInput" title="upload csv">
所以,@ K3N绝对给了我一个有价值的拼图和异步函数课程。然而,主要的问题是python没有识别它从javascript接收的字符串输入,所以我想我会与所有人分享我的旅程。我最后将字符串转换为2d javascript数组,然后我shift()
关闭列名的第一行,转置剩余的行,并清除所有来自英语的愚蠢的东西,阻止它工作(引号和撇号)。现在我可以pd.DataFrame(dict(zip(colNames,cols)))
并运行我在同一个.csv
上运行的所有计算,当我从我的文件系统中读取它时。这是完整的脚本,基本上修复@ K3N向我展示了加上pythonify(arr)
函数:
<input type="file" id="CSVFileInput" title="upload csv">
function handleFiles() {
var file = this.files[0]; // "this" is the calling element
var fr = new FileReader();
fr.onload = function() {
var outputBuffer = this.result.split("\r"); //split on row delimeter
var temp=[];
var command;
outputBuffer.forEach(function(element){
element=element.replace("\n",""); //each was also delimeter by this, so strip it
temp.push(element.split("\t")); //split on cols
});
outputBuffer=temp;//yay now outputBuffer is 2d array
var names=outputBuffer.shift(); //pop names rown from output Buffer
temp=[]; //reset temp
for(let i=0 ; i<outputBuffer[0].length ; i++){ //transpose remaining rows to provide arrays for names
temp[i]=[];
for(let j=0; j<outputBuffer.length ; j++){
temp[i][j]=outputBuffer[j][i];
}
}
outputBuffer=temp; //yay now is transposed
command="colNames ="+pythonify(names); //declare colNames array on python side
IPython.notebook.kernel.execute(command); //send command to kernel
for(let i=0 ; i< outputBuffer.length ; i++){ //loop appends columns on python side
command="cols.append("+pythonify(outputBuffer[i])+")";
IPython.notebook.kernel.execute(command); //send command to kernel
}
};
fr.readAsText(file); // invoked asynchronously
}
function pythonify (arr){ //turns javascript array into string representation of python list
var out= '[';
for(let i=0 ; i<arr.length ; i++){
var element=arr[i];
element=element.replace(/\"/g,'\\"').replace(/'/g,"\\'"); //replaces quotes with python escaped version
out+='r"'+element+'"';
if(i<arr.length-1){ //skip last comma
out+=',';
}
}
out+=']';
return out;
}
document.getElementById("CSVFileInput").addEventListener("change", handleFiles);