1

Node打开选择文件夹弹框

 1 year ago
source link: https://www.clzczh.top/2023/03/22/file-dialog/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Node打开选择文件夹弹框

用脚手架的那套东西写了一个工具,但是想要一个用Node去打开选择文件夹弹框的效果,来设置操作根目录。但是,Node本身没有这个API。

node执行python脚本

Node本身没有提供打开选择文件夹弹框的API,但是Python的tkinter是有这个功能的。所以可以用Python写好脚本来打开选择文件夹,然后通过Node来执行python脚本。

Python脚本也是非常的简单。

import tkinter as tk
import tkinter.filedialog

dirPaths = tkinter.filedialog.askdirectory()

if(len(dirPaths) == 0):
  print('None')
else:
  print(dirPaths)

Node执行Python脚本需要通过Node提供的child_process来创建子进程(exec),它会将紫禁城的输入以回调函数参数的形式一次性返回。

ESM里使用__dirname

因为我用的是ESM模式写的,所以是不能直接使用__dirname的。这里稍微吹一下下ChatGPT。

202303101405304.png

启用ESM模式则是在package.json中,添加type: "module"

当然,答案有点小瑕疵,实际上得到的是当前文件的绝对地址,并且前面会有文件协议。所以需要进行一些处理。

202303101449081.png
202303101450972.png
import { exec } from 'child_process';
import { EOL } from 'os';  // 回车、换行,通过JSON.stringify()能够观测到
import path from 'path';

const dirname = import.meta.url.slice(8, import.meta.url.lastIndexOf('/'));

const p = new Promise((resolve, reject) => {
  exec(path.join(dirname, 'dialog.py'), (err, stdout, stderr) => {
    if (err) {
      reject(new Error(err));
    } else if (stderr) {
      reject(new Error(stderr));
    } else if (stdout) {
      const result = stdout.trim().split(EOL).toString();  // 将返回的结果去掉前后的空格以及回车换行
      resolve(result);
    }
  })
});

p.then(val => {
    console.log(val);
})
202303101504714.gif

中文路径问题

python输出中文是会乱码的,所以当我们选择的路径有中文的话,就会出现问题。

202303101511099.gif

在网上找到一些解决方案说是改环境变量。但是,本人想要的效果是只需要下载工具,就能直接使用。而不需要手动修改。所以最好的方案还是在代码上做文章。

最后,功夫不负有心人。找到一个改变标准输入输出的默认编码的方案。

import io
import sys

#改变标准输出的默认编码
sys.stdout= io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')

所以,需要小修改Python代码,添加上面的内容。

202303101515280.png
202303101518197.gif

将python程序打包成exe文件

上面通过Node来执行python脚本,实际上是需要电脑有安装Python,但是这样子当然是不太好的,有种捆绑的感觉。和Python的耦合度过高,所以最终考虑将python程序打包成exe文件。

py打包为exe文件需要依赖pyinstaller

更多:如何将python程序打包成exe文件_py打包成exe_一朝乐的博客-CSDN博客

安装pyinstaller可能会遇到的问题以及解决方案:

如何将python程序打包成exe文件_py打包成exe_一朝乐的博客-CSDN博客

202303101535010.png

除了dist外,生成的东西都能删掉,因为其他都是都是编译的时候生成的。只有dist是我们有我们想要的exe文件。

直接双击生成的exe文件,也会打开选择文件夹弹框。

202303101541813.gif

代码也需要修改成执行exe文件,而不再是python文件。

import { exec } from 'child_process';
import { EOL } from 'os';  // 回车、换行,通过JSON.stringify()能够观测到
import path from 'path';

const dirname = import.meta.url.slice(8, import.meta.url.lastIndexOf('/'));

const p = new Promise((resolve, reject) => {
  exec(path.join(dirname, 'dist', 'dialog.exe'), (err, stdout, stderr) => {
    if (err) {
      reject(new Error(err));
    } else if (stderr) {
      reject(new Error(stderr));
    } else if (stdout) {
      const result = stdout.trim().split(EOL).toString();  // 将返回的结果去掉前后的空格以及回车换行
      resolve(result);
    }
  })
});

p.then(val => {
    console.log(val);
})

效果和前面一样。

还可以编写一个sh文件,帮我们生成exe文件,并且删除编译中生成的一些其他文件。

run.sh

#!/bin/bash
pyinstaller -F dialog.py
rm build/ -rf
rm dialog.specs

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK