batch-filesubprocesspopencx-freeze

how to run batch files from frozen python code


I have two Python scripts, the first one asks the user about the version of a commercial tool (and the corresponding Python version) that the user has. Based on that, the script runs a batch file to run the second script using the different Python version the user selected. the code in the first script includes:

p = subprocess.Popen(args=batch_loc, shell=False, creationflags=subprocess.CREATE_NEW_CONSOLE)

where batch_loc is the location of the batch file (inside the patch file: py -3.7-32 C:\code\source\NB_converter_gui.py where 3.7-32 is the Python version selected by the user)

The code runs without any issues.

But, when I use cx_freeze to package the code, running the second code from the batch file tries to use libraries from the frozen libraries and not from the Python version on the user side. The error code is below.

My question is, how to run batch files (python scripts) from frozen Python code and use the Python version on the user side?

Here is the error:

C:\>py -3.7-32 C:\code\source\NB_converter_gui.py psse34
Traceback (most recent call last):
  File "C:\code\base_none\source\NB_converter_gui.py", line 480, in <module>
    main(psse)
  File "C:\code\base_none\source\NB_converter_gui.py", line 473, in main
    root = tk.Tk()
  File "C:\Python37\lib\tkinter\__init__.py", line 2023, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: Can't find a usable init.tcl in the following directories:
    {C:\code\base_none\lib\tcl8.6} C:/Python37/lib/tcl8.6 C:/lib/tcl8.6 C:/lib/tcl8.6 C:/library C:/library C:/tcl8.6.9/library C:/tcl8.6.9/library

C:/code/base_none/lib/tcl8.6/init.tcl: version conflict for package "Tcl": have 8.6.9, need exactly 8.6.12
version conflict for package "Tcl": have 8.6.9, need exactly 8.6.12
    while executing
"package require -exact Tcl 8.6.12"
    (file "C:/code/base_none/lib/tcl8.6/init.tcl" line 19)
    invoked from within
"source C:/code/base_none/lib/tcl8.6/init.tcl"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 [list source $tclfile]"


This probably means that Tcl wasn't installed properly.

Solution

  • Thanks to @Mofi, the issue was with PYTHONPATH. When a subprocess is called in the first code, the first code's environment variables (parent) are passed to the second code (child) by default. So the solution is to pass the system environments without the PYTHONPATH of the first code python directory in the path

    env = os.environ
    if env.get('PYTHONPATH'):
        del env['PYTHONPATH']
    if os.environ.get('TCL_LIBRARY'):   
        del os.environ['TCL_LIBRARY']
    if os.environ.get('TK_LIBRARY'):
        del os.environ['TK_LIBRARY']
    if os.environ.get('PYTZ_TZDATADIR'):
        del os.environ['PYTZ_TZDATADIR']
    
    
    p = subprocess.Popen(args=file_loc, shell=False, creationflags=subprocess.CREATE_NEW_CONSOLE, env=env)
    

    The second code will run without inheriting PYTHONPATH or other variables from the first code.