I wrote a simple Nodejs script that checks if Python is installed with the specific version and if not it will install a portable version via zip.
Executing Python works fine but when I try to install sth via pip with :
.\python.exe -m pip intstall xzy
it says that pip is not installed.
When i check the Scripts and lib folder where python is installed i see the pip.exe
here is my script :
import { exec, spawn } from 'child_process';
import fs from 'fs';
import axios from 'axios';
import os from 'os';
import path from 'path';
const platform = os.platform();
async function getPythonPath(version: string): Promise<string> {
const pythonFolder = path.join("public", "python", version)
const pythonCmd = path.join(pythonFolder, 'python');
if (fs.existsSync(pythonFolder)) {
return platform === "win32" ? pythonCmd + ".exe" : pythonCmd;
}
let pythonUrl: string,
pythonZipPath: string,
unzipCmd: string,
pipCmd: string;
if (platform === 'win32') {
pythonUrl = `https://www.python.org/ftp/python/${version}/python-${version}-embed-amd64.zip`;
pythonZipPath = path.join(os.tmpdir(), `python-${version}.zip`);
unzipCmd = `7z x ${pythonZipPath} -o${pythonFolder}`;
pipCmd = `${pythonCmd}.exe ${path.join(pythonFolder, 'get-pip.py')}`;
} else if (platform === 'darwin') {
pythonUrl = `https://www.python.org/ftp/python/${version}/python-${version}-macosx10.9.pkg`;
pythonZipPath = path.join(os.tmpdir(), `python-${version}.pkg`);
unzipCmd = `sudo installer -pkg ${pythonZipPath} -target /`;
pipCmd = `sudo ${pythonCmd} ${path.join(pythonFolder, 'get-pip.py')}`;
} else {
throw new Error('Unsupported platform');
}
try {
console.log(`Downloading Python ${version}...`);
const response = await axios({
method: 'get',
url: pythonUrl,
responseType: 'stream',
});
const fileStream = fs.createWriteStream(pythonZipPath);
response.data.pipe(fileStream);
await new Promise<void>((resolve, reject) => {
fileStream.on('finish', resolve);
fileStream.on('error', reject);
});
await new Promise<void>((resolve, reject) => {
console.log(`Unzipping Python ${version}...`);
exec(unzipCmd, (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
// Download get-pip.py
console.log('Downloading get-pip.py...');
const getPipUrl = 'https://bootstrap.pypa.io/get-pip.py';
const getPipScriptPath = path.join(pythonFolder, 'get-pip.py');
const getPipResponse = await axios({
method: 'get',
url: getPipUrl,
});
fs.writeFileSync(getPipScriptPath, getPipResponse.data);
await new Promise<void>((resolve, reject) => {
console.log('Installing pip...');
exec(pipCmd, (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
return platform === "win32" ? pythonCmd + ".exe" : pythonCmd;
} catch (error) {
throw error;
}
}
export async function pyrun(scriptPath: string, pythonVersion: string, callback: (text: string) => void, onerror: (text: string) => void): Promise<void> {
return new Promise<void>(async (resolve, reject) => {
const pythonExecutable = await getPythonPath(pythonVersion);
const command = `${pythonExecutable} ${scriptPath}`;
exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
resolve();
}
if (stdout && callback) {
callback(stdout);
}
if (stderr && onerror) {
onerror(stderr);
}
});
});
}
this is my try to run it :
import path from "path";
import { pyrun } from "../basic-py-run";
async function main() {
const version = '3.9.0';
const installScript = path.join('public', 'python', version) + ' -m pip install cowsay';
await pyrun(installScript, version, (text) => {
console.log(text)
}, (error) => {
console.error(error);
});
}
main();
I saw that you try to use python embed on win32:
if (platform === 'win32') { pythonUrl = `https://www.python.org/ftp/python/${version}/python-${version}-embed-amd64.zip`;
After running get_pip.py with Python embed, you have to modify your pythonXX._pth file in the root folder.
Add Lib\site-packages, to get something like this:
pythonXX.zip
.
Lib\site-packages
# Uncomment to run site.main() automatically
#import site
You can get more info on this answer: https://stackoverflow.com/a/60829519/2226755
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With