我正在开发一个包含电子角度前端的应用程序,该应用程序调用一些Python任务(使用RobotFramework)。整个Typescript代码与Python代码之间的通信由节点模块Python-shell
处理。我到达了该项目,试图使事情变得“干净”,并希望创建一个虚拟环境,以便我们能够更轻松地管理Python版本和应用程序的Python依赖关系。
问题在于,它显然引入了一个新的错误,除此以外,我们真的无法以其他方式重现该错误:
第一次对项目运行npm start
,然后单击特定的按钮(启动Python后台任务)时,您会看到作业按预期执行,但是按钮保持“锁定”状态,就好像它仍在等待Python给出其输出。
这是MyService
服务中按钮调用的代码:
executePython(robotScriptFilePath: string): Observable<RobotMessage> {
const path = this.electronService.remote.require('path');
process.env.PATH = process.env.PATH + ';' + path.join(this.electronService.remote.app.getAppPath(), environment.driverPath);
// process.env.PYTHONDONTWRITEBYTECODE = 'true';
process.env.PYTHONUNBUFFERED = 'true';
const options = {
env: process.env,
pythonPath: this.pythonPath, // points to the virtualenv's python.exe
scriptPath: this.robotFolderPath, // points to virtualenv's site-packages
args: ['--pythonpath', this.externalLibrariesPath, '--outputdir', this.logsFolderPath, robotScriptFilePath]
};
return new Observable(observer => {
PythonShell.run('run.py', options, (err, stdout) => {
if (err) {
observer.next(new RobotMessage(false, err.message));
observer.complete();
} else {
observer.next(new RobotMessage(true, stdout.toString()));
observer.complete();
}
});
return { unsubscribe() {} };
});
}
我首先认为它与 pycache 有某种关系,因为它仅发生一次,因此我设置了env-var PYTHONDONTWRITEBYTECODE
以查看它是否正在复制bug可靠,但是它没有任何改变,所以我认为它与我们认为Python-shell处理通信的方式有关,因此设置了PYTHONUNBUFFERED
env-var。
我在两台计算机上尝试了后者:在一台计算机上工作,但在另一台计算机上什么都没有改变。
我是否错过了一些有关虚拟环境的东西,或者会阻止我使用这种设置?但最重要的是,你们对导致这种奇怪行为的原因有任何线索吗?
此外,请注意,除了虚拟环境之外,Python也没有“花哨的东西”:我们只是按原样使用RobotFramework的库。
RobotMessage
类定义:
export class RobotMessage {
isSuccess: boolean;
message: string;
constructor(isSucess: boolean, message: string) {
this.isSuccess = isSucess;
this.message = message;
}
}
MyService
定义:
export class MyService {
private robotFolderPath: string;
private externalLibrariesPath: string;
private logsFolderPath: string;
private robotScriptsFolderPath: string;
private libraries: string[];
private resources: string[];
private scriptFileExtension: string;
private separator: string;
private pythonPath: string;
private chromedriverPath: string;
constructor(private electronService: ElectronService, private stepService: StepService) {
this.robotFolderPath = environment.robotFramework.robotFolderPath;
this.externalLibrariesPath = environment.robotFramework.externalLibrariesPath;
this.logsFolderPath = environment.robotFramework.logsPath;
this.robotScriptsFolderPath = environment.robotFramework.robotScriptsFolderPath;
this.libraries = ['SeleniumLibrary'];
this.resources = [];
this.scriptFileExtension = '.robot';
this.separator = ' ';
this.pythonPath = this.electronService.isWindows ? environment.winPythonPath : environment.nixPythonPath;
}