7

How can we install python3 in wine for 32bit ubuntu ?

Using winetricks python2.7 is possible but my app is written in python3

I don't have windows to test my application so I am going this hard way

4
  • Python 2.7 and Python 3.4 are both natively available and probably even preinstalled on Ubuntu. Do you have a special reason for wanting to run it in wine?
    – Byte Commander
    Sep 25, 2015 at 10:58
  • 5
    yes I want to deploy my python3 app to windows exe and i don't have windows to test it. using pyinstaller Sep 25, 2015 at 11:01
  • Byte Commander, just answer the damn question if you can. If you can't, then don't say anything Sep 4, 2020 at 0:25
  • Found this answer on stackoverflow for python3 stackoverflow.com/a/67857537
    – kaptaan
    Jun 6, 2021 at 9:32

7 Answers 7

5

Python 3.7 now works in the newer versions of wine. This user used wine 4.14 to install python 3.7.4 and I'm currently using Python 3.7.6 in wine 5.0-rc3. I'm able to run pyinstaller for cross-compiling and I can test the resulting exe packages and my source code in wine without issue. The apps I'm testing have a GUI based on PyQt5.

I first tried @Hibou57's approach using embedded-python which does not require newer wine versions. While this works for a minimal python install, I ran into a lot of annoying problems later on requiring a number of hacks. I gave up on this approach when I couldn't figure out how to install numpy within embedded python in wine.

To install Python 3.7.6 in wine:

  1. Add the official wine repository to apt to get the lastest dev versions
  2. Install the developer version of wine sudo apt install winehq-devel.
  3. Just download and run the Python 3.7.6 exe install file within wine wine cmd /c python-3.7.6.exe.

The script below is what I'm using to install python 3.7.6 inside a docker container for cross compiling using a Ubuntu 18.04 image. I'm also using a 64-bit wine prefix. Note that some parts of this script deal with docker-specific issues.

#!/bin/bash

set -e

echo "---------------------------------"
echo "-------- setup wine prefix ------"
echo "---------------------------------"
# We need the developer version of wine.  We need at least version 4.14 (see link).
# This is the earliest version I've seen reported to work with python3 well
# Without this, we'd have to run the embedded install of python which is riddled
# with annoying issues.

# see: https://appdb.winehq.org/objectManager.php?sClass=version&iId=38187

echo "------ Installing required apt packages ------"
apt update
apt install -y wget gnupg software-properties-common apt-utils

echo "------ Add latest wine repo ------"
# Need at least wine 4.14 to install python 3.7
dpkg --add-architecture i386
wget -nc https://dl.winehq.org/wine-builds/winehq.key
apt-key add winehq.key
apt-add-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ bionic main'
apt update

# Add repo for faudio package.  Required for winedev
add-apt-repository -y ppa:cybermax-dexter/sdl2-backport

echo "-------- Install wine-dev ------"

apt install -y \
    winehq-devel \
    winetricks \
    xvfb        # This is for making a dummy X server disply 

echo "------ Download python ------"
wget https://www.python.org/ftp/python/3.7.6/python-3.7.6-amd64.exe
#wget https://www.python.org/ftp/python/3.7.6/python-3.7.6.exe

echo "------ Init wine prefix ------"
WINEPREFIX=~/.wine64 WINARCH=win64 winetricks \
    corefonts \
    win10

# Setup dummy screen
Xvfb :0 -screen 0 1024x768x16 &
jid=$!

echo "------ Install python ------"
DISPLAY=:0.0 WINEPREFIX=~/.wine64 wine cmd /c \
    python-3.7.6-amd64.exe \
    /quiet \
    PrependPath=1 \
    && echo "Python Installation complete!"
# Display=:0.0 redirects wine graphical output to the dummy display.  
# This is to avoid docker errors as the python installer requires a display, 
# even when quiet install is specified.
3
  • "Just download and run the Python 3.7.6 exe install file within wine…" You just glossed over the only important part of your answer :(
    – Auspex
    May 21, 2022 at 14:40
  • @Auspex, did u read the bash code in my answer? I show how to do this in the "install python" chunk.
    – RTbecard
    May 22, 2022 at 16:32
  • Well, given that it is, as journalists used to say "below the fold", no...
    – Auspex
    May 24, 2022 at 10:48
1

I have a similar issue: I have to develop a Python3 application on Ubuntu which is to be delivered on Windows. I wanted to use pyInstaller to produce a Windows executable from Wine, since I unfortunately do not have access to a Windows box. But I failed to install Python3 on Wine too.

However, may be there is another option: using what’s called a python embeddable zip archive. See here: 3.8. Embedded Distribution (docs.python.org).

You can download it from releases download pages, as in this one (an example) : Python 3.5.2 (python.org).

You have two:

  • Windows x86-64 embeddable zip file
  • Windows x86 embeddable zip file

This means you have to ask the client if he/she is running a 32 bits or a 64 bits Windows.

That’s not perfect, since if Python3 is not able to run in Wine, there is no way to test the application’s Windows version. But at least, that’s a way to package something which should run on Windows, with the hope the source will behave on Windows the same way it behave on Ubuntu. At least, you should develop on the Ubuntu side, using a Python virtual environment. See 28.3. venv — Creation of virtual environments.

1
  • I've been stuck on this exact issue... and I also arrived at this solution. However, for those using embedded python in wine, note that pip needs some tweaks to work correctly (if that important for you). See here.
    – RTbecard
    Dec 31, 2019 at 19:56
1

actually You can use python3 on wine:

basically all You need is to install python3 on a windows machine (for You only, not for all Users), and copy the whole directory to the wine machine.

Alternatively You can download it from Python releases download pages, as mentioned in the post of Hibou57

Then add following paths in the wine registry : "c:\python37;C:\python37\Scripts;..." and everything works fine.

I provided some convenient Scripts on Github to do that automatically for Ubuntu

However, You need to decide first if You want to Install WINE STABLE, WINE DEVELOP or WINE STAGING (I suggest WINE DEVELOP).

Then You need to decide which Architecture (32 Bit or 64 Bit Wine) and then, on top of that You can install 32 or 64 Bit Python 2.7 or Python 3.7 by copying as explained before.

the whole process is a bit lengthy and there are many details You need to install, here the scripts :

#!/bin/bash
# ../home/install_wine.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    chmod +x "${my_dir}/lib_bash/*.sh"
    source "${my_dir}/lib_bash/lib_color.sh"
    source "${my_dir}/lib_bash/lib_retry.sh"
    source "${my_dir}/lib_bash/lib_wine_install.sh"
}

include_dependencies  # me need to do that via a function to have local scope of my_dir




clr_bold clr_green "Install WINE"
check_wine_version

clr_green "add 386 Architecture"
retry sudo dpkg --add-architecture i386
clr_green "add Wine Keys"
retry wget https://dl.winehq.org/wine-builds/winehq.key
sudo apt-key add winehq.key
sudo apt-add-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ xenial main'
clr_green "Wine Packages Update"
retry sudo apt-get update
clr_green "Wine Packages Install"
retry sudo apt-get install --install-recommends winehq-${wine_version}
retry sudo apt-get install -y cabextract
retry sudo apt-get install -y libxml2
retry sudo apt-get install -y libpng-dev

clr_green "Install latest Winetricks"
sudo rm -f /usr/bin/winetricks
retry sudo wget --directory-prefix=/usr/bin/ https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
sudo chmod +x /usr/bin/winetricks
retry sudo winetricks -q --self-update
clr_green "Install latest Winetricks - done"

clr_green "done"
clr_green "******************************************************************************************************************"
clr_bold clr_green "FINISHED installing WINE and WINETRICKS"
clr_green "******************************************************************************************************************"

#!/bin/bash
# ../home/install_wine_machine.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    chmod +x "${my_dir}/lib_bash/*.sh"
    source "${my_dir}/lib_bash/lib_color.sh"
    source "${my_dir}/lib_bash/lib_retry.sh"
    source "${my_dir}/lib_bash/lib_wine_install.sh"
}

include_dependencies  # me need to do that via a function to have local scope of my_dir

clr_bold clr_green "Install Wine Machine"
check_wine_prefix
check_wine_arch
check_wine_windows_version
check_headless_xvfb

clr_green "Setup Wine Machine at ${WINEPREFIX}, WINEARCH=${WINEARCH}, wine_windows_version=${wine_windows_version}"
mkdir -p ${WINEPREFIX}
wine_drive_c_dir=${WINEPREFIX}/drive_c
# xvfb-run --auto-servernum winecfg # fails marshal_object couldnt get IPSFactory buffer for interface ...

if [[ ${xvfb_framebuffer_service_active} == "True" ]]; then sudo service xvfb stop ; fi   # winecfg fails if xvfb server is running
winecfg
if [[ ${xvfb_framebuffer_service_active} == "True" ]]; then sudo service xvfb start ; fi     # winecfg fails if xvfb server is running

echo "Disable GUI Crash Dialogs"
winetricks nocrashdialog

echo "Set Windows Version to ${wine_windows_version}"
winetricks -q ${wine_windows_version}

echo "Install common Packets"

retry winetricks -q windowscodecs
retry winetricks -q msxml3

clr_green "done"
clr_green "******************************************************************************************************************"
clr_bold clr_green "FINISHED installing Wine Machine ${WINEPREFIX}"
clr_green "******************************************************************************************************************"

#!/bin/bash
# ../home/install_wine_python2_preinstalled.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    chmod +x "${my_dir}/lib_bash/*.sh"
    source "${my_dir}/lib_bash/lib_color.sh"
    source "${my_dir}/lib_bash/lib_retry.sh"
    source "${my_dir}/lib_bash/lib_wine_install.sh"
}

include_dependencies  # me need to do that via a function to have local scope of my_dir

# if used outside github/travis You need to set :
# WINEARCH=win32    for 32 Bit Wine
# WINEARCH=         for 64 Bit Wine
# WINEPREFIX defaults to ${HOME}/.wine   or you need to pass it via environment variable
# if running headless, the xvfb service needs to run


clr_bold clr_green "Install Python 2.7 on WINE"
check_wine_prefix
check_wine_arch

wine_drive_c_dir=${WINEPREFIX}/drive_c
decompress_dir=${HOME}/bitranox_decompress
mkdir -p ${decompress_dir}

python_version_short=python27
python_version_doc="Python 2.7"

clr_green "Download ${python_version_doc} Binaries from https://github.com/bitranox/binaries_${python_version_short}_wine/archive/master.zip"
retry wget -nc --no-check-certificate -O ${decompress_dir}/binaries_${python_version_short}_wine-master.zip https://github.com/bitranox/binaries_${python_version_short}_wine/archive/master.zip

clr_green "Unzip ${python_version_doc} Master to ${HOME}"
unzip -nqq ${decompress_dir}/binaries_${python_version_short}_wine-master.zip -d ${decompress_dir}

if [[ "${WINEARCH}" == "win32" ]]
    then
        clr_green "Joining Multipart Zip in ${decompress_dir}/binaries_${python_version_short}_wine-master/bin"
        cat ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/python*_wine_32* > ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/joined_${python_version_short}.zip
        add_pythonpath="c:/Python27-32;c:/Python27-32/Scripts"
    else
        clr_green "Joining Multipart Zip in ${decompress_dir}/binaries_${python_version_short}_wine-master/bin"
        cat ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/python*_wine_64* > ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/joined_${python_version_short}.zip
        add_pythonpath="c:/Python27-64;c:/Python27-64/Scripts"
    fi

clr_green "Unzip ${python_version_doc} to ${wine_drive_c_dir}"
unzip -qq ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/joined_${python_version_short}.zip -d ${wine_drive_c_dir}

prepend_path_to_wine_registry ${add_pythonpath}

clr_green "done"
clr_green "******************************************************************************************************************"
clr_bold clr_green "FINISHED installing Python 2.7 on Wine Machine ${WINEPREFIX}"
clr_green "******************************************************************************************************************"

#!/bin/bash
# ../home/install_wine_python3_preinstalled.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    chmod +x "${my_dir}/lib_bash/*.sh"
    source "${my_dir}/lib_bash/lib_color.sh"
    source "${my_dir}/lib_bash/lib_retry.sh"
    source "${my_dir}/lib_bash/lib_wine_install.sh"
}

include_dependencies  # me need to do that via a function to have local scope of my_dir

# if used outside github/travis You need to set :
# WINEARCH=win32    for 32 Bit Wine
# WINEARCH=""       for 64 Bit Wine
# WINEPREFIX defaults to ${HOME}/.wine   or you need to pass it via environment variable

# if running headless, the xvfb service needs to run

clr_bold clr_green "Install Python 3.7 on WINE"
check_wine_prefix
check_wine_arch


wine_drive_c_dir=${WINEPREFIX}/drive_c
decompress_dir=${HOME}/bitranox_decompress
mkdir -p ${decompress_dir}

python_version_short=python37
python_version_doc="Python 3.7"

clr_green "Download ${python_version_doc} Binaries from https://github.com/bitranox/binaries_${python_version_short}_wine/archive/master.zip"
retry wget -nc --no-check-certificate -O ${decompress_dir}/binaries_${python_version_short}_wine-master.zip https://github.com/bitranox/binaries_${python_version_short}_wine/archive/master.zip

clr_green "Unzip ${python_version_doc} Master to ${HOME}"
unzip -nqq ${decompress_dir}/binaries_${python_version_short}_wine-master.zip -d ${decompress_dir}

if [[ "${WINEARCH}" == "win32" ]]
    then
        clr_green "Joining Multipart Zip in ${decompress_dir}/binaries_${python_version_short}_wine-master/bin"
        cat ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/python*_wine_32* > ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/joined_${python_version_short}.zip
        add_pythonpath="c:/Python37-32;c:/Python37-32/Scripts"
    else
        clr_green "Joining Multipart Zip in ${decompress_dir}/binaries_${python_version_short}_wine-master/bin"
        cat ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/python*_wine_64* > ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/joined_${python_version_short}.zip
        add_pythonpath="c:/Python37-64;c:/Python37-64/Scripts"
    fi

clr_green "Unzip ${python_version_doc} to ${wine_drive_c_dir}"
unzip -qq ${decompress_dir}/binaries_${python_version_short}_wine-master/bin/joined_${python_version_short}.zip -d ${wine_drive_c_dir}

prepend_path_to_wine_registry ${add_pythonpath}


clr_green "done"
clr_green "******************************************************************************************************************"
clr_bold clr_green "FINISHED installing Python 3.7 on Wine Machine ${WINEPREFIX}"
clr_green "******************************************************************************************************************"

#!/bin/bash
# ../home/install_wine_git_portable.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    chmod +x "${my_dir}/lib_bash/*.sh"
    source "${my_dir}/lib_bash/lib_color.sh"
    source "${my_dir}/lib_bash/lib_retry.sh"
    source "${my_dir}/lib_bash/lib_wine_install.sh"
}

include_dependencies  # me need to do that via a function to have local scope of my_dir

# if used outside github/travis You need to set :
# WINEARCH=win32    for 32 Bit Wine
# WINEARCH=         for 64 Bit Wine
# WINEPREFIX defaults to ${HOME}/.wine   or you need to pass it via environment variable

# if running headless, the xvfb service needs to run

clr_bold clr_green "Install Git Portable"
check_wine_prefix
check_wine_arch

wine_drive_c_dir=${WINEPREFIX}/drive_c
decompress_dir=${HOME}/bitranox_decompress
mkdir -p ${decompress_dir}

clr_green "Download Git Portable Binaries"
retry wget -nc --no-check-certificate -O ${decompress_dir}/binaries_portable_git-master.zip https://github.com/bitranox/binaries_portable_git/archive/master.zip

clr_green "Unzip Git Portable Binaries Master to ${decompress_dir}"
unzip -nqq ${decompress_dir}/binaries_portable_git-master.zip -d ${decompress_dir}

if [[ "${WINEARCH}" == "win32" ]]
    then
        clr_green "Joining Multipart Zip in ${decompress_dir}/binaries_portable_git-master/bin"
        cat ${decompress_dir}/binaries_portable_git-master/bin/PortableGit32* > ${decompress_dir}/binaries_portable_git-master/bin/joined_PortableGit.zip
        add_git_path="c:/PortableGit32/cmd"
    else
        clr_green "Joining Multipart Zip in ${decompress_dir}/binaries_portable_git-master/bin"
        cat ${decompress_dir}/binaries_portable_git-master/bin/PortableGit64* > ${decompress_dir}/binaries_portable_git-master/bin/joined_PortableGit.zip
        add_git_path="c:/PortableGit64/cmd"
    fi

clr_green "Unzip Git Portable Binaries to ${wine_drive_c_dir}"
unzip -qq ${decompress_dir}/binaries_portable_git-master/bin/joined_PortableGit.zip -d ${wine_drive_c_dir}

prepend_path_to_wine_registry ${add_git_path}

clr_green "done"
clr_green "******************************************************************************************************************"
clr_bold clr_green "FINISHED installing Git Portable on Wine Machine ${WINEPREFIX}"
clr_green "******************************************************************************************************************"

#!/bin/bash
# ../home/lib_bash/lib_color.sh
#
# Constants and functions for terminal colors.
# Author: Max Tsepkov <[email protected]>
# Manual see https://github.com/mercuriev/bash_colors
#


CLR_ESC="\033["

# All these variables has a function with the same name, but in lower case.
#
CLR_RESET=0             # reset all attributes to their defaults
CLR_RESET_UNDERLINE=24  # underline off
CLR_RESET_REVERSE=27    # reverse off
CLR_DEFAULT=39          # set underscore off, set default foreground color
CLR_DEFAULTB=49         # set default background color

CLR_BOLD=1              # set bold
CLR_BRIGHT=2            # set half-bright (simulated with color on a color display)
CLR_UNDERSCORE=4        # set underscore (simulated with color on a color display)
CLR_REVERSE=7           # set reverse video

CLR_BLACK=30            # set black foreground
CLR_RED=31              # set red foreground
CLR_GREEN=32            # set green foreground
CLR_BROWN=33            # set brown foreground
CLR_BLUE=34             # set blue foreground
CLR_MAGENTA=35          # set magenta foreground
CLR_CYAN=36             # set cyan foreground
CLR_WHITE=37            # set white foreground

CLR_BLACKB=40           # set black background
CLR_REDB=41             # set red background
CLR_GREENB=42           # set green background
CLR_BROWNB=43           # set brown background
CLR_BLUEB=44            # set blue background
CLR_MAGENTAB=45         # set magenta background
CLR_CYANB=46            # set cyan background
CLR_WHITEB=47           # set white background


# check if string exists as function
# usage: if fn_exists "sometext"; then ... fi
function fn_exists
{
    type -t "$1" | grep -q 'function'
}

# iterate through command arguments, o allow for iterative color application
function clr_layer
{
    # default echo setting
    CLR_ECHOSWITCHES="-e"
    CLR_STACK=""
    CLR_SWITCHES=""
    ARGS=("$@")

    # iterate over arguments in reverse
    for ((i=$#; i>=0; i--)); do
        ARG=${ARGS[$i]}
        # echo $ARG
        # set CLR_VAR as last argtype
        firstletter=${ARG:0:1}

        # check if argument is a switch
        if [ "$firstletter" = "-" ] ; then
            # if -n is passed, set switch for echo in clr_escape
            if [[ $ARG == *"n"* ]]; then
                CLR_ECHOSWITCHES="-en"
                CLR_SWITCHES=$ARG
            fi
        else
            # last arg is the incoming string
            if [ -z "$CLR_STACK" ]; then
                CLR_STACK=$ARG
            else
                # if the argument is function, apply it
                if [ -n "$ARG" ] && fn_exists $ARG; then
                    #continue to pass switches through recursion
                    CLR_STACK=$($ARG "$CLR_STACK" $CLR_SWITCHES)
                fi
            fi
        fi
    done

    # pass stack and color var to escape function
    clr_escape "$CLR_STACK" $1;
}

# General function to wrap string with escape sequence(s).
# Ex: clr_escape foobar $CLR_RED $CLR_BOLD
function clr_escape
{
    local result="$1"
    until [ -z "${2:-}" ]; do
    if ! [ $2 -ge 0 -a $2 -le 47 ] 2>/dev/null; then
        echo "clr_escape: argument \"$2\" is out of range" >&2 && return 1
    fi
        result="${CLR_ESC}${2}m${result}${CLR_ESC}${CLR_RESET}m"
    shift || break
    done

    echo "$CLR_ECHOSWITCHES" "$result"
}

function clr_reset           { clr_layer $CLR_RESET "$@";           }
function clr_reset_underline { clr_layer $CLR_RESET_UNDERLINE "$@"; }
function clr_reset_reverse   { clr_layer $CLR_RESET_REVERSE "$@";   }
function clr_default         { clr_layer $CLR_DEFAULT "$@";         }
function clr_defaultb        { clr_layer $CLR_DEFAULTB "$@";        }
function clr_bold            { clr_layer $CLR_BOLD "$@";            }
function clr_bright          { clr_layer $CLR_BRIGHT "$@";          }
function clr_underscore      { clr_layer $CLR_UNDERSCORE "$@";      }
function clr_reverse         { clr_layer $CLR_REVERSE "$@";         }
function clr_black           { clr_layer $CLR_BLACK "$@";           }
function clr_red             { clr_layer $CLR_RED "$@";             }
function clr_green           { clr_layer $CLR_GREEN "$@";           }
function clr_brown           { clr_layer $CLR_BROWN "$@";           }
function clr_blue            { clr_layer $CLR_BLUE "$@";            }
function clr_magenta         { clr_layer $CLR_MAGENTA "$@";         }
function clr_cyan            { clr_layer $CLR_CYAN "$@";            }
function clr_white           { clr_layer $CLR_WHITE "$@";           }
function clr_blackb          { clr_layer $CLR_BLACKB "$@";          }
function clr_redb            { clr_layer $CLR_REDB "$@";            }
function clr_greenb          { clr_layer $CLR_GREENB "$@";          }
function clr_brownb          { clr_layer $CLR_BROWNB "$@";          }
function clr_blueb           { clr_layer $CLR_BLUEB "$@";           }
function clr_magentab        { clr_layer $CLR_MAGENTAB "$@";        }
function clr_cyanb           { clr_layer $CLR_CYANB "$@";           }
function clr_whiteb          { clr_layer $CLR_WHITEB "$@";          }

# Outputs colors table
function clr_dump
{
    local T='gYw'

    echo -e "\n                 40m     41m     42m     43m     44m     45m     46m     47m";

    for FGs in '   0m' '   1m' '  30m' '1;30m' '  31m' '1;31m' \
               '  32m' '1;32m' '  33m' '1;33m' '  34m' '1;34m' \
               '  35m' '1;35m' '  36m' '1;36m' '  37m' '1;37m';
    do
        FG=${FGs// /}
        echo -en " $FGs \033[$FG  $T  "
        for BG in 40m 41m 42m 43m 44m 45m 46m 47m; do
            echo -en " \033[$FG\033[$BG  $T  \033[0m";
        done
        echo;
    done

    echo
    clr_bold "    Code     Function           Variable"
    echo \
'    0        clr_reset          $CLR_RESET
    1        clr_bold           $CLR_BOLD
    2        clr_bright         $CLR_BRIGHT
    4        clr_underscore     $CLR_UNDERSCORE
    7        clr_reverse        $CLR_REVERSE

    30       clr_black          $CLR_BLACK
    31       clr_red            $CLR_RED
    32       clr_green          $CLR_GREEN
    33       clr_brown          $CLR_BROWN
    34       clr_blue           $CLR_BLUE
    35       clr_magenta        $CLR_MAGENTA
    36       clr_cyan           $CLR_CYAN
    37       clr_white          $CLR_WHITE

    40       clr_blackb         $CLR_BLACKB
    41       clr_redb           $CLR_REDB
    42       clr_greenb         $CLR_GREENB
    43       clr_brownb         $CLR_BROWNB
    44       clr_blueb          $CLR_BLUEB
    45       clr_magentab       $CLR_MAGENTAB
    46       clr_cyanb          $CLR_CYANB
    47       clr_whiteb         $CLR_WHITEB
'
}

function fail {
  clr_bold clr_red "${1}" >&2
  exit 1
}

## make it possible to call functions without source include
# Check if the function exists (bash specific)
if [[ ! -z "$1" ]]
    then
        if declare -f "${1}" > /dev/null
        then
          # call arguments verbatim
          "$@"
        else
          # Show a helpful error
          function_name="${1}"
          library_name="${0}"
          fail "\"${function_name}\" is not a known function name of \"${library_name}\""
        fi
    fi

#!/bin/bash
# ../home/lib_bash/lib_retry.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    source "${my_dir}/lib_color.sh"
}

include_dependencies  # we need to do that via a function to have local scope of my_dir


function fail {
  clr_bold clr_red "${1}" >&2
  exit 1
}


function retry {
  local n=1
  local max=5
  local delay=5
  while true; do
    my_command="${@}"
    "$@" && break || {
      if [[ $n -lt $max ]]; then
        ((n++))
        clr_bold clr_red "Command \"${my_command}\" failed. Attempt ${n}/${max}:"
        sleep $delay;
      else
        fail "The command \"${my_command}\" has failed after ${n} attempts."
      fi
    }
  done
}


## make it possible to call functions without source include
# Check if the function exists (bash specific)
if [[ ! -z "$1" ]]
    then
        if declare -f "${1}" > /dev/null
        then
          # call arguments verbatim
          "$@"
        else
          # Show a helpful error
          function_name="${1}"
          library_name="${0}"
          fail "\"${function_name}\" is not a known function name of \"${library_name}\""
        fi
    fi

#!/bin/bash
# ../home/lib_bash/lib_wine_install.sh

function include_dependencies {
    local my_dir="$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )"  # this gives the full path, even for sourced scripts
    chmod +x "${my_dir}/*.sh"
    source "${my_dir}/lib_color.sh"
    source "${my_dir}/lib_retry.sh"
}

include_dependencies  # we need to do that via a function to have local scope of my_dir


function fail {
  clr_bold clr_red "${1}" >&2
  exit 1
}


function check_wine_version {
    if [[ -z ${wine_version} ]]
        then
            clr_bold clr_red "WARNING - no wine_version in environment set - set now to default: devel"
            echo "available Versions: stable, devel, staging"
            export wine_version="devel"
        fi
}


function check_wine_prefix {
    ## set wine prefix to ${HOME}/.wine if not given by environment variable
    if [[ -z ${WINEPREFIX} ]]
        then
            clr_bold clr_red "WARNING - no WINEPREFIX in environment - set now to ${HOME}/.wine"
            export WINEPREFIX=${HOME}/.wine
        fi
}

function check_wine_arch {
    if [[ -z ${WINEARCH} ]]
        then
            clr_bold clr_red "WARNING - no WINEARCH in environment - will install 64 Bit Wine"
            clr_bold clr_red "in Order to install 32Bit You need to set WINEARCH=\"win32\""
            clr_bold clr_red "in Order to install 64Bit You need to set WINEARCH=\"\""
        fi
}


function check_wine_windows_version {
    if [[ -z ${wine_windows_version} ]]
        then
            clr_bold clr_red "WARNING - no wine_windows_version in environment - set now to win10"
            clr_bold clr_red "available Versions: win10, win2k, win2k3, win2k8, win31, win7, win8, win81, win95, win98, winxp"
            export wine_windows_version="win10"
        fi
}


function check_headless_xvfb {
    clr_green "Check if we run headless and xvfb Server is running"
    export xvfb_framebuffer_service_active="False"
    systemctl is-active --quiet xvfb && export xvfb_framebuffer_service_active="True"
    # run winetricks with xvfb if needed
    if [[ ${xvfb_framebuffer_service_active} == "True" ]]
        then
            clr_green "we run headless, xvfb service is running"
        else
            clr_green "we run on normal console, xvfb service is not running"
        fi
}

function prepend_path_to_wine_registry {
    add_pythonpath="${1}"
    clr_green "add Path Settings to Registry"
    wine_current_reg_path="`wine reg QUERY \"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\" /v PATH | grep REG_SZ | sed 's/^.*REG_SZ\s*//'`"
    wine_new_reg_path="${add_pythonpath};${wine_current_reg_path}"
    wine reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /t REG_SZ /v PATH /d "${wine_new_reg_path}" /f
    wine_actual_reg_path="`wine reg QUERY \"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\" /v PATH | grep REG_SZ | sed 's/^.*REG_SZ\s*//'`"
    clr_green "adding Path done"
    clr_bold clr_green "Wine Registry PATH=${wine_actual_reg_path}"
}


## make it possible to call functions without source include
# Check if the function exists (bash specific)
if [[ ! -z "$1" ]]
    then
        if declare -f "${1}" > /dev/null
        then
          # call arguments verbatim
          "$@"
        else
          # Show a helpful error
          function_name="${1}"
          library_name="${0}"
          fail "\"${function_name}\" is not a known function name of \"${library_name}\""
        fi
    fi

1

Microsoft offers free Windows VM images for download. They're meant to be used to test websites in Internet Explorer, but they're still fully featured copies of Windows on which you could install Python 3 and test your application in a more faithful Windows environment than Wine

3
  • 1
    yes we can always use VM's but my processor doesn't support virtualization (KVM!). Sep 28, 2015 at 10:35
  • @RohitKaradkar According to VirtualBox's documentation, Windows 7 and earlier (Which are used for all but 3 vms) do not require hardware virtualisation.
    – 3Doubloons
    Sep 28, 2015 at 16:06
  • Your connection is not private Attackers might be trying to steal your information from dev.modern.ie (for example, passwords, messages, or credit cards). Learn more NET::ERR_CERT_COMMON_NAME_INVALID Nov 11, 2020 at 11:30
0

Here is the simple guide that I've used:

#1 Use Wine 2.4
apt install add-apt-repository
add-apt-repository ppa:wine/wine-builds
apt install --install-recommends winehq-devel


#2 Use winetricks (a newer one that what is available in the repo)
wget  https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
./winetricks -q win10
./winetricks vcrun2015

After that just execute wine python-3.4.4.exe or whatever your Python is. If you are using python 3.5 the "install" option will not be visible but if you click in the center of the installer it will complete successfully and python works.

Source: http://realtechtalk.com/How_To_Install_python_34_35_and_up_on_Linux_with_wine_Working_Solution-2288-articles

0

A ready-made docker image: https://hub.docker.com/r/cdrx/pyinstaller-windows

Hopefully it saves some people's time.

0

As many answers said, there is Wine. But they all made complicated scripts, while we just need some logic to install Python 3 on Wine. As I know, Wine uses code from Windows XP, and since Python since version 3.9 does not support Windows XP, you will have to use Python 3.8.9, which is the last version supported by Windows XP. Here's what I did on my Linux (MX Linux - Wine 6.22, stable branch, 64 bits computer):

sudo apt install wine-stable wine64 -y  # use package wine32 instead of wine64 if you install Python 3.8.9 32 bits version
wget -O "python-install.exe" "https://www.python.org/ftp/python/3.8.9/python-3.8.9-amd64.exe"  # you can also download the 32bits python version here: https://www.python.org/ftp/python/3.8.9/python-3.8.9-amd64.exe
wine python-install.exe  # launchs a new window containing python install, check the add python.exe to path box, click install to hard drive, wait for it install and click close
wine py  # can also be `py3` by example or many others depending on which are allready taken **in wine** (not in your linux real installation!)

The last command launches the Python 3.8.9 shell, so you can run print("Hello world !") to make sure it's installed correctly. Also, since its running in Wine, os.name is nt and platform.system() is Windows. Now, to compile your programm:

cd /folder/containing/my/python/script
wine py -m pip install pyinstaller
wine py -m pyinstaller --onefile myscript.py  # the option --onefile creates a portable script where everything required by python (not external programms that are ran by the script !) are inclued in the same .exe file

Note that if you installed Python 3.8.9 32 bits on Wine, your executable will be compatible with 32bits and 64bits Windows (thanks to Wow64 that "emulates" the 32 bits programms to make they can run on 64bits computers) but 64bits Python will produce executable for only 64bits Windows.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .