Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Portable Python pip execution fails on "module pip not found"

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();
like image 883
user3110458 Avatar asked Nov 28 '25 20:11

user3110458


1 Answers

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

like image 159
Sky Voyager Avatar answered Nov 30 '25 11:11

Sky Voyager



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!