Repository: pyinstaller/pyinstaller

Issue:
Problem with hook-_tkinter.py using Python3.7 on MacOS
My application builds and runs perfectly on the same machine using Python3.6 (venv). But with Python 3.7 (installed from python.org) the following occurs:

```
14638 INFO: Excluding import 'tkinter'
14639 INFO: Import to be excluded not found: 'FixTk'
14639 INFO: Loading module hook "hook-xml.etree.cElementTree.py"...
14640 INFO: Loading module hook "hook-_tkinter.py"...
14642 ERROR: Tcl/Tk improperly installed on this system.
```

Then when I try and run the app:

```
Traceback (most recent call last):
  File "PyInstaller/loader/rthooks/pyi_rth__tkinter.py", line 28, in <module>
FileNotFoundError: Tcl data directory "/var/folders/nl/2wxh3z313l129zpzq2f8ww5m0000gn/T/_MEILUmJRc/tcl" not found.
[2195] Failed to execute script pyi_rth__tkinter
```

I suspect it is to do with the fact that Python3.7 comes with Tcl/Tk 8.6 built in and the hook script isn't properly aware of this but I don't know enough about how it all works to be able to make any contribution.
As my application doesn't actually use tkinter I can work round it using `--exclude-module tkinter` but the problem's there for those who do neeed it.


Discussion:
For information the above occurs with both Pyinstaller 3.4 and the current development version.
The problems comes from the fact that Python3.7 is bundled with its own version of Tcl and Tk, and when the script `hook-_tkinter.py` is run, a test on the path of the Tcl and Tk library is too simple and make it fail (more details below). So, for those still looking for answers on how to run with Tkinter, here are two ways to add what is missing (tested both in the PyInstaller3.4 and the development `PyInstaller3.5.dev0+0ffa574bf`).

- The first, pointed out by tazzben in #3770 that I didn't know of is the following:
> If this script is bundled single directory style, the .app file does not start initially. However, it will start if you manually create the folders "tk" and "tcl" in the MacOS folder within the .app bundle. For the .app file to work on a computer without python 3.7 preinstalled, you will also have to copy the tk8.6 and tcl8.6 folders, icons, and config files (*.sh) from /Library/Frameworks/Python.framework/Versions/3.7/lib/ and paste them in the MacOS folder in the bundle. You should _not_ copy the system TCL/TK files (as suggested in other issues) as they will conflict -- I imagine that is a fix in versions prior to 3.6.5.

In other words, here are the command to run in order to achieve this result:
```shell
pyinstaller --windowed myapp.py
cd dist/myapp.app/Contents/MacOs
mkdir tcl tk
cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/tcl* tcl/
cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/tk* tk/
cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/Tk* tk/ 
```
After this, the executable named `myapp` in this folder `dist/myapp.app/Contents/MacOs` can be executed and will run properly.

- The second is a bit more tricky. Locate the file `PyInstaller/hooks/hook-_tkinter.py` (if using a virtual environment it is easy to locate, otherwise, it is probably in `/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PyInstaller/hooks/hook-_tkinter.py`).
The problem comes from the function `_find_tcl_tk` starting line 148 of the file, and more precisely from the test line 183.
```python
        path_to_tcl = bins[0][1]
->      if 'Library/Frameworks' in path_to_tcl:
            tcl_tk = _find_tcl_tk_darwin_frameworks(bins)
        # Tcl/Tk compiled as on Linux other Unixes.
        # For example this is the case of Tcl/Tk from macports.
        else:
            tcl_tk = _find_tcl_tk_dir()
```
Indeed if the Tcl/Tk libraries come from the Python package, their path is something like `/Library/Frameworks/Python.framework/Versions/3.7/lib/libtcl8.6.dylib`, which will account to a True value in the test. However, the call of the function `_find_tcl_tk_darwin_frameworks` is looking for the names `Tcl` and `Tk` in order to make the full path for the framework `[/System]/Library/Frameworks/Tcl.framework/Ressources/Scripts/Tcl` (and similarly for Tk), which fails with the provided paths coming from the Python distribution.
A simple shortcut to make this work is the following:
```python
#change line 183
if 'Library/Frameworks' in path_to_tcl:
#by adding a condition:
if 'Library/Frameworks' in path_to_tcl and 'Python' not in path_to_tcl:
```
This should do the trick to include properly the libraries. As a result, two folders `tcl` and `tk` will be created in `myapp.app/Contents/Ressources` and two links are added in the `MacOs` directory.
I don't know if I should make a commit of this change, or let people more advanced do this (or a better way).


_Remark: as of now, with both ways, the problem of the application crashing when launching the .app (cf #3820 ) is problematic, and is not solved by modifying of the code, putting everything to a single file using option `--onefile` and turning it in an app bundle by hand (or with appify)._
@AmbroiseGrau Thank you for your analysis (which I did only scan in a second). What about providing a pull-request to fix the issue?
thanks @AmbroiseGrau. The second way of your's, helped me to resolve my long pending issue. 🥇 
Thanks @AmbroiseGrau, 
with the Second Solution, My pain has long gone.
```
python : 3.6
Freezing : fbs
OS : MacOS 10.14.4
```
The same problem occurs on Python 2.7.16. We had that with PySide2 5.13.0 .
This issue was fixed by @AmbroiseGrau on 2018-10-25. What prevents it to be incorporated into the release as a fix?
@AmbroiseGrau You saved my @55 with this second fix thank you, seriously. Modifying PyInstaller/hooks/hook-_tkinter.py resolved the issue
Thank you!
Thank you very much!
Thanks 👍 
Merci for the fix @AmbroiseGrau!  curious though why this hasn't yet been merged into master? As of this writing (15 months since the fix was reported!), I still had to find this thread and do it manually... Do I need to make a PR? 😂more than happy to add those 30 characters to the codebase 😂
I encounter this problem when building on MacOS from a makespec file generated on windows. If i make a makespec file from MacOS it runs fine.
> The problems comes from the fact that Python3.7 is bundled with its own version of Tcl and Tk, and when the script `hook-_tkinter.py` is run, a test on the path of the Tcl and Tk library is too simple and make it fail (more details below). So, for those still looking for answers on how to run with Tkinter, here are two ways to add what is missing (tested both in the PyInstaller3.4 and the development `PyInstaller3.5.dev0+0ffa574bf`).
> 
> * The first, pointed out by tazzben in #3770 that I didn't know of is the following:
> 
> > If this script is bundled single directory style, the .app file does not start initially. However, it will start if you manually create the folders "tk" and "tcl" in the MacOS folder within the .app bundle. For the .app file to work on a computer without python 3.7 preinstalled, you will also have to copy the tk8.6 and tcl8.6 folders, icons, and config files (*.sh) from /Library/Frameworks/Python.framework/Versions/3.7/lib/ and paste them in the MacOS folder in the bundle. You should _not_ copy the system TCL/TK files (as suggested in other issues) as they will conflict -- I imagine that is a fix in versions prior to 3.6.5.
> 
> In other words, here are the command to run in order to achieve this result:
> 
> ```shell
> pyinstaller --windowed myapp.py
> cd dist/myapp.app/Contents/MacOs
> mkdir tcl tk
> cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/tcl* tcl/
> cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/tk* tk/
> cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/Tk* tk/ 
> ```
> 
> After this, the executable named `myapp` in this folder `dist/myapp.app/Contents/MacOs` can be executed and will run properly.
> 
> * The second is a bit more tricky. Locate the file `PyInstaller/hooks/hook-_tkinter.py` (if using a virtual environment it is easy to locate, otherwise, it is probably in `/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PyInstaller/hooks/hook-_tkinter.py`).
>   The problem comes from the function `_find_tcl_tk` starting line 148 of the file, and more precisely from the test line 183.
> 
> ```python
>         path_to_tcl = bins[0][1]
> ->      if 'Library/Frameworks' in path_to_tcl:
>             tcl_tk = _find_tcl_tk_darwin_frameworks(bins)
>         # Tcl/Tk compiled as on Linux other Unixes.
>         # For example this is the case of Tcl/Tk from macports.
>         else:
>             tcl_tk = _find_tcl_tk_dir()
> ```
> 
> Indeed if the Tcl/Tk libraries come from the Python package, their path is something like `/Library/Frameworks/Python.framework/Versions/3.7/lib/libtcl8.6.dylib`, which will account to a True value in the test. However, the call of the function `_find_tcl_tk_darwin_frameworks` is looking for the names `Tcl` and `Tk` in order to make the full path for the framework `[/System]/Library/Frameworks/Tcl.framework/Ressources/Scripts/Tcl` (and similarly for Tk), which fails with the provided paths coming from the Python distribution.
> A simple shortcut to make this work is the following:
> 
> ```python
> #change line 183
> if 'Library/Frameworks' in path_to_tcl:
> #by adding a condition:
> if 'Library/Frameworks' in path_to_tcl and 'Python' not in path_to_tcl:
> ```
> 
> This should do the trick to include properly the libraries. As a result, two folders `tcl` and `tk` will be created in `myapp.app/Contents/Ressources` and two links are added in the `MacOs` directory.
> I don't know if I should make a commit of this change, or let people more advanced do this (or a better way).
> 
> _Remark: as of now, with both ways, the problem of the application crashing when launching the .app (cf #3820 ) is problematic, and is not solved by modifying of the code, putting everything to a single file using option `--onefile` and turning it in an app bundle by hand (or with appify)._

tks for  your help ,
my mac os is :10.15.3
python vision:3.8.1

when pyinstaller is done ,the ***.app cannot run still .but the ***.exc can run with a terminal window.
is there a solution for my issue.tks for your great on my case ag.
> > The problems comes from the fact that Python3.7 is bundled with its own version of Tcl and Tk, and when the script `hook-_tkinter.py` is run, a test on the path of the Tcl and Tk library is too simple and make it fail (more details below). So, for those still looking for answers on how to run with Tkinter, here are two ways to add what is missing (tested both in the PyInstaller3.4 and the development `PyInstaller3.5.dev0+0ffa574bf`).
> > 
> > * The first, pointed out by tazzben in #3770 that I didn't know of is the following:
> > 
> > > If this script is bundled single directory style, the .app file does not start initially. However, it will start if you manually create the folders "tk" and "tcl" in the MacOS folder within the .app bundle. For the .app file to work on a computer without python 3.7 preinstalled, you will also have to copy the tk8.6 and tcl8.6 folders, icons, and config files (*.sh) from /Library/Frameworks/Python.framework/Versions/3.7/lib/ and paste them in the MacOS folder in the bundle. You should _not_ copy the system TCL/TK files (as suggested in other issues) as they will conflict -- I imagine that is a fix in versions prior to 3.6.5.
> > 
> > 
> > In other words, here are the command to run in order to achieve this result:
> > ```shell
> > pyinstaller --windowed myapp.py
> > cd dist/myapp.app/Contents/MacOs
> > mkdir tcl tk
> > cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/tcl* tcl/
> > cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/tk* tk/
> > cp -R /Library/Frameworks/Python.framework/Versions/3.7/lib/Tk* tk/ 
> > ```
> > 
> > 
> > After this, the executable named `myapp` in this folder `dist/myapp.app/Contents/MacOs` can be executed and will run properly.
> > 
> > * The second is a bit more tricky. Locate the file `PyInstaller/hooks/hook-_tkinter.py` (if using a virtual environment it is easy to locate, otherwise, it is probably in `/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PyInstaller/hooks/hook-_tkinter.py`).
> >   The problem comes from the function `_find_tcl_tk` starting line 148 of the file, and more precisely from the test line 183.
> > 
> > ```python
> >         path_to_tcl = bins[0][1]
> > ->      if 'Library/Frameworks' in path_to_tcl:
> >             tcl_tk = _find_tcl_tk_darwin_frameworks(bins)
> >         # Tcl/Tk compiled as on Linux other Unixes.
> >         # For example this is the case of Tcl/Tk from macports.
> >         else:
> >             tcl_tk = _find_tcl_tk_dir()
> > ```
> > 
> > 
> > Indeed if the Tcl/Tk libraries come from the Python package, their path is something like `/Library/Frameworks/Python.framework/Versions/3.7/lib/libtcl8.6.dylib`, which will account to a True value in the test. However, the call of the function `_find_tcl_tk_darwin_frameworks` is looking for the names `Tcl` and `Tk` in order to make the full path for the framework `[/System]/Library/Frameworks/Tcl.framework/Ressources/Scripts/Tcl` (and similarly for Tk), which fails with the provided paths coming from the Python distribution.
> > A simple shortcut to make this work is the following:
> > ```python
> > #change line 183
> > if 'Library/Frameworks' in path_to_tcl:
> > #by adding a condition:
> > if 'Library/Frameworks' in path_to_tcl and 'Python' not in path_to_tcl:
> > ```
> > 
> > 
> > This should do the trick to include properly the libraries. As a result, two folders `tcl` and `tk` will be created in `myapp.app/Contents/Ressources` and two links are added in the `MacOs` directory.
> > I don't know if I should make a commit of this change, or let people more advanced do this (or a better way).
> > _Remark: as of now, with both ways, the problem of the application crashing when launching the .app (cf #3820 ) is problematic, and is not solved by modifying of the code, putting everything to a single file using option `--onefile` and turning it in an app bundle by hand (or with appify)._
> 
> tks for your help ,
> my mac os is :10.15.3
> python vision:3.8.1
> 
> when pyinstaller is done ,the ***.app cannot run still .but the ***.exc can run with a terminal window.
> is there a solution for my issue.tks for your great on my case ag.

Having the exact same problem anyone can help please??


Resolving patch:
diff --git a/PyInstaller/hooks/hook-_tkinter.py b/PyInstaller/hooks/hook-_tkinter.py
--- a/PyInstaller/hooks/hook-_tkinter.py
+++ b/PyInstaller/hooks/hook-_tkinter.py
@@ -107,12 +107,13 @@ def _warn_if_activetcl_or_teapot_installed(tcl_root, tcltree):
             """ % init_resource)
 
 
-def _find_tcl_tk_darwin_frameworks(binaries):
+def _find_tcl_tk_darwin_system_frameworks(binaries):
     """
     Get an OS X-specific 2-tuple of the absolute paths of the top-level
     external data directories for both Tcl and Tk, respectively.
 
-    Under OS X, Tcl and Tk are installed as Frameworks requiring special care.
+    This function finds the OS X system installation of Tcl and Tk.
+    System OS X Tcl and Tk are installed as Frameworks requiring special care.
 
     Returns
     -------
@@ -186,10 +187,15 @@ def _find_tcl_tk(hook_api):
 
         # _tkinter depends on Tcl/Tk compiled as frameworks.
         path_to_tcl = bins[0][1]
-        if 'Library/Frameworks' in path_to_tcl:
-            tcl_tk = _find_tcl_tk_darwin_frameworks(bins)
+        # OS X system installation of Tcl/Tk.
+        # [/System]/Library/Frameworks/Tcl.framework/Resources/Scripts/Tcl
+        if 'Library/Frameworks/Tcl.framework' in path_to_tcl:
+            tcl_tk = _find_tcl_tk_darwin_system_frameworks(bins)
         # Tcl/Tk compiled as on Linux other Unixes.
-        # For example this is the case of Tcl/Tk from macports.
+        # This is the case of Tcl/Tk from macports and Tck/Tk built into
+        # python.org OS X python distributions.
+        # python.org built-in tcl/tk is located at
+        # /Library/Frameworks/Python.framework/Versions/3.x/lib/libtcl8.6.dylib
         else:
             tcl_tk = _find_tcl_tk_dir()
 


Test patch: