poetry icon indicating copy to clipboard operation
poetry copied to clipboard

Can't use tkinter in virtual environment created by poetry

Open vitalije opened this issue 4 years ago • 11 comments

  • OS version and name: Ubuntu 20.04
  • Poetry version: 1.1.7
  • Link of a Gist with the contents of your pyproject.toml file: https://gist.github.com/vitalije/77d16343bf8f0a99ec0946f2586edf5b

Issue

I have several python installations. Using one that I have compiled myself (*Python 3.9.6) with support of latest stable tk/tcl (8.6.11). This python when invoked directly has full support for tkinter library. However, when I create new virtual environment using:

poetry env use /path/to/my/python3.9.6
poetry shell
python -m tkinter

I get the error that python was not configured to use tkinter module.

When I manually add links lib/tcl8.6 and lib/tk8.6 to the virtual environment in ~/.cache/pypoetry/virtualenvs/mleo.../lib/, python can use tkinter afterwards.

I was expecting that poetry would add those links when creating new virtual environment.

vitalije avatar Jul 27 '21 13:07 vitalije

I too have had this issue. After some testing, it seems fixed with the current version of Poetry. Try reinstalling it. Here are some fixes...

  • I had Poetry 1.1.8 installed and had this error, 1.1.12 fixed it
  • Check your virtualenv's pyvenv.cfg and look for the virtualenv version.
    • Run poetry env info -p for the path to your virtualenv
    • The virtualenv version should look like virtualenv = 20.*.*
      • 20.7.2 was broken, while 20.10.0 was fixed
  • Ensure that Tkinter worked with other Python versions
    • You may have to rebuild / reinstall your version
    • I ran Python 3.9.6 for both broken and fixed versions

I hope this helped you. I know it is a bit late, but hopefully someone else stumbles upon this and it fixes their issue. 😄

My working version of pyvenv.cfg...

BD103 avatar Jan 03 '22 19:01 BD103

I think I'm having a similar issue.

$ which poetry
/Users/rben01/.local/bin/poetry

$ python --version
Python 3.10.6

$ poetry --version
Poetry (version 1.2.1)

$ poetry run python --version
Python 3.10.6

$ python -m tkinter  # displays tk window, produces no output

$ poetry run python -m tkinter
Traceback (most recent call last):
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/runpy.py", line 187, in _run_module_as_main
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/runpy.py", line 146, in _get_module_details
    return _get_module_details(pkg_main_name, error)
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/runpy.py", line 110, in _get_module_details
    __import__(pkg_name)
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/tkinter/__init__.py", line 37, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

rben01 avatar Oct 07 '22 18:10 rben01

This does not reproduce for me in a container -- I suspect that your Python simply has not been built against TK.

docker run --rm -i --entrypoint /bin/bash python:3.10 <<-EOF
apt-get update
apt-get install -y xvfb
pip install poetry==1.2.1
poetry new foo
pushd foo
poetry run python -m tkinter
xvfb-run poetry run python -m tkinter
EOF

neersighted avatar Oct 07 '22 18:10 neersighted

@neersighted But python -m tkinter works fine.

rben01 avatar Oct 07 '22 18:10 rben01

Are you sure that you are using the same interpreter? I would try to poetry env use the Python executable you have configured for TK.

neersighted avatar Oct 07 '22 18:10 neersighted

$ poetry env use "$(which python)"
Using virtualenv: /Users/rben01/Library/Caches/pypoetry/virtualenvs/base-wTklQcO3-py3.10

$ poetry run python -m tkinter
Traceback (most recent call last):
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/runpy.py", line 187, in _run_module_as_main
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/runpy.py", line 146, in _get_module_details
    return _get_module_details(pkg_main_name, error)
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/runpy.py", line 110, in _get_module_details
    __import__(pkg_name)
  File "/nix/store/8b68yhhj335ajv25iqc2cdmp78csdlcv-python3-3.10.6/lib/python3.10/tkinter/__init__.py", line 37, in <module>
    import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

rben01 avatar Oct 07 '22 19:10 rben01

Ok, I tracked this down to poetry seemingly ignoring poetry env use /path/to/python in some cases. That is, you can have the following (pseudo-bash):

$ readlink "$(poetry run which python)"
/path/a/python3.10

$ poetry env use /path/b/python3.10

$ readlink "$(poetry run which python)"
/path/a/python3.10

Perhaps you have to poetry env use /path/to/python before even creating the environment? If so, it's incredibly misleading that poetry env use is a no-op once the environment has been created.

rben01 avatar Oct 09 '22 21:10 rben01

Ran into this as well.

Looks like pyenv had a similar issue with tkinter: https://github.com/pyenv/pyenv/issues/1375

myartsev avatar Jan 18 '23 09:01 myartsev

If you use pyenv to manage your Python versions (which you should), you'll run into this issue. I was able to fix it by following these two steps.

Step 1: Installing Necessary System Packages

Using tkinter with pyenv can be tricky due to missing dependencies.

First, let's make sure we have installed the necessary system packages for tkinter.

In most Linux systems, you can install them with the following commands:

sudo apt-get update
sudo apt-get install tk-dev

On macOS, you can use Homebrew to achieve the same:

brew install tcl-tk

Step 2: Linking the Correct Tcl/Tk Versions

Next, make sure you link the correct versions of Tcl/Tk when installing Python. pyenv builds Python in your environment, but if you don't have the required dependencies, like the Tk/Tcl libraries, it'll build Python without them.

If the Python version you want to use is already installed on your system, you'll need to uninstall it before proceeding. For example:

pyenv uninstall 3.11.3

When installing a new Python version with pyenv, use the following commands:

For Linux:

sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git

env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install <version>

For macOS, after installing tcl-tk with brew:

brew install openssl readline sqlite3 xz zlib

env LDFLAGS="-L$(brew --prefix [email protected])/lib -L$(brew --prefix readline)/lib -L$(brew --prefix sqlite3)/lib -L$(brew --prefix xz)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix tcl-tk)/lib" \
CPPFLAGS="-I$(brew --prefix [email protected])/include -I$(brew --prefix readline)/include -I$(brew --prefix sqlite3)/include -I$(brew --prefix xz)/include -I$(brew --prefix zlib)/include -I$(brew --prefix tcl-tk)/include" \
PKG_CONFIG_PATH="$(brew --prefix [email protected])/lib/pkgconfig:$(brew --prefix readline)/lib/pkgconfig:$(brew --prefix sqlite3)/lib/pkgconfig:$(brew --prefix xz)/lib/pkgconfig:$(brew --prefix zlib)/lib/pkgconfig:$(brew --prefix tcl-tk)/lib/pkgconfig" \
pyenv install <version>

Replace <version> with the version of Python you want to install. After that, you should be able to import tkinter in your pyenv Python environment.

Note that I couldn't get tkinter to work with pyenv on Python 3.11.0, but it worked perfectly on 3.11.2.

xshapira avatar Jun 03 '23 10:06 xshapira

If you use pyenv to manage your Python versions (which you should), you'll run into this issue. I was able to fix it by following these two steps.

Step 1: Installing Necessary System Packages

Using tkinter with pyenv can be tricky due to missing dependencies.

First, let's make sure we have installed the necessary system packages for tkinter.

In most Linux systems, you can install them with the following commands:

sudo apt-get update
sudo apt-get install tk-dev

On macOS, you can use Homebrew to achieve the same:

brew install tcl-tk

Step 2: Linking the Correct Tcl/Tk Versions

Next, make sure you link the correct versions of Tcl/Tk when installing Python. pyenv builds Python in your environment, but if you don't have the required dependencies, like the Tk/Tcl libraries, it'll build Python without them.

If the Python version you want to use is already installed on your system, you'll need to uninstall it before proceeding. For example:

pyenv uninstall 3.11.3

When installing a new Python version with pyenv, use the following commands:

For Linux:

sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git

env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install <version>

For macOS, after installing tcl-tk with brew:

brew install openssl readline sqlite3 xz zlib

env LDFLAGS="-L$(brew --prefix [email protected])/lib -L$(brew --prefix readline)/lib -L$(brew --prefix sqlite3)/lib -L$(brew --prefix xz)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix tcl-tk)/lib" \
CPPFLAGS="-I$(brew --prefix [email protected])/include -I$(brew --prefix readline)/include -I$(brew --prefix sqlite3)/include -I$(brew --prefix xz)/include -I$(brew --prefix zlib)/include -I$(brew --prefix tcl-tk)/include" \
PKG_CONFIG_PATH="$(brew --prefix [email protected])/lib/pkgconfig:$(brew --prefix readline)/lib/pkgconfig:$(brew --prefix sqlite3)/lib/pkgconfig:$(brew --prefix xz)/lib/pkgconfig:$(brew --prefix zlib)/lib/pkgconfig:$(brew --prefix tcl-tk)/lib/pkgconfig" \
pyenv install <version>

Replace <version> with the version of Python you want to install. After that, you should be able to import tkinter in your pyenv Python environment.

Note that I couldn't get tkinter to work with pyenv on Python 3.11.0, but it worked perfectly on 3.11.2.

Worked for me on Python 1 3.11.1 , thanks a lot!

vitahoang avatar Jun 14 '23 09:06 vitahoang

Fwiw I got this on macos (m1, sonoma) and I checked what version of python was running inside poetry shell, then exited that shell, ran the same version, tried import tkinter as tk, got the same error, then realized that yes — I'd installed python-tk — but my poetry shell was referencing python 3.12 and I only had [email protected]. Resolved with

brew install [email protected]

djeikyb avatar Jan 19 '24 21:01 djeikyb

@djeikyb the issue you are facing is not a poetry issue IMHO.

This would seem that you didn't have the required system dependencies available for the version of python used for your project virtual environment.

Once the dependencies are installed and available you can specify the use of the correct python version for your virtual environment.

If you want to use the system site installed package, you can also attempt to use https://python-poetry.org/docs/configuration/#virtualenvsoptionssystem-site-packages. However, that is also bound to the site of the python version being used.

abn avatar Mar 23 '24 11:03 abn

Closing this issue as most of the information here is stale and maintainers cannot reproduce it to debug.

If you encounter this issue please raise a new issue with relevant details and a usable reproducer.

abn avatar Mar 23 '24 11:03 abn

I am not using poetry anymore so it is not terribly important to me, but here is today's experiment that still produces the same error.

>cd /tmp
>mkdir proba
>cd proba
>poetry --version
Poetry (version 1.8.1)
>poetry init
... setting the required python version to ^3.9
...
Generated file

[tool.poetry]
name = "proba"
version = "0.1.0"
description = ""
authors = ["vitalije <[email protected]>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.9"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Do you confirm generation? (yes/no) [yes]
>poetry env use /opt/programi/Python/bin/python3.9
Creating virtualenv proba-NvBQKm7d-py3.9 in /home/vitalije/.cache/pypoetry/virtualenvs
Using virtualenv: /home/vitalije/.cache/pypoetry/virtualenvs/proba-NvBQKm7d-py3.9
>poetry shell
Spawning shell within /home/vitalije/.cache/pypoetry/virtualenvs/proba-NvBQKm7d-py3.9
. /home/vitalije/.cache/pypoetry/virtualenvs/proba-NvBQKm7d-py3.9/bin/activate
> python -m tkinter
Traceback (most recent call last):
  File "/opt/programi/Python/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/programi/Python/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/opt/programi/Python/lib/python3.9/tkinter/__main__.py", line 7, in <module>
    main()
  File "/opt/programi/Python/lib/python3.9/tkinter/__init__.py", line 4557, in _test
    root = Tk()
  File "/opt/programi/Python/lib/python3.9/tkinter/__init__.py", line 2270, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: Can't find a usable tk.tcl in the following directories: 
    /usr/local/lib/tcl8.6/tk8.6 /usr/local/lib/tk8.6 /home/vitalije/.cache/pypoetry/virtualenvs/proba-NvBQKm7d-py3.9/lib/tk8.6 /home/vitalije/.cache/pypoetry/virtualenvs/proba-NvBQKm7d-py3.9/lib/tk8.6 /home/vitalije/.cache/pypoetry/virtualenvs/lib/tk8.6 /home/vitalije/.cache/pypoetry/virtualenvs/proba-NvBQKm7d-py3.9/library
>

However running directly python executable with -m tkinter succeeds

>/opt/programi/Python/bin/python3.9 -m tkinter

I expect that after instructing poetry to use selected interpreter with:

> poetry env use .....some/path/python

it would create environment fully compatible with the given python interpreter installation. Instead it creates environment that is missing some packages.

Maybe my expectation is not valid, but that's what I understood this command should accomplish.

Best regards.

vitalije avatar Mar 23 '24 16:03 vitalije

Note that in the reported error python says it could not find tcl.tk installation in the several directories. This list of directories doesn't include lib folder of the original python installation. Poetry did not make a copy of the required files from that folder nor it did change the search path. Maybe the reason you can't reproduce the bug is that you have tcl.tk installed in some other folder mentioned in the search path. In that case python from the environment generated by poetry is not using the original tcl.tk, but some other instance possibly a different version too.

If I manually copy necessary files to the environment created by poetry, tkinter module works. Therefore I am blaming poetry for doing its job partially. The module tkinter is a part of the python standard library, so I don't think it should be listed as a dependency.

vitalije avatar Mar 23 '24 16:03 vitalije

@vitalije if you can, can you please try the following?

  1. Using poetry run instead of poetry shell.
poetry run python -m tkinter
  1. Creating a virtual environment using the standard lib venv.
/opt/programi/Python/bin/python3.9 -m venv /tmp/py39-venv
/tmp/py39-venv/bin/python -m tkinter
source /tmp/py39-venv/bin/activate
python -m tkinter
deactivate
  1. Creating a virtual environment using the virtualenv package installed with Poetry.
poetry_python_bin=$(head -n1 $(which poetry) | sed s/'#!'//)
"$poetry_python_bin" -m virtualenv /tmp/py39-venv-poetry
/tmp/py39-venv-poetry/bin/python -m tkinter
source /tmp/py39-venv-poetry/bin/activate
python -m tkinter
deactivate

abn avatar Mar 23 '24 18:03 abn

  1. poetry run python -m tkinter produces the same error
  2. the same error
  3. In this case, the second line produces the following error:
    bash: /usr/bin/env bash: No such file or directory
    > echo $poetry_python_bin
    /usr/bin/env bash
    

I guess you wished to set this variable to the python interpreter used by poetry?

So, I did the following:

>/opt/programi/Python/bin/python3.9 -m pip install poetry
>/opt/programi/Python/bin/poetry --version
Poetry (version 1.8.2)
>head -n 1 /opt/programi/Python/bin/poetry
#!/opt/programi/Python/bin/python3.9

So, I set the poetry_python_bin to this value and continued with the 3rd script you've suggested and the result is the same error.

Even, starting from the scratch using the newly installed poetry to create a new project and a new environment produced the same error.

If I manually add links lib/tcl8.6 and lib/tk8.6 pointing to the corresponding folders in /opt/programi/Python/lib/{tcl8.6,tk.86}, then afterwards, python -m tkinter works normally.

vitalije avatar Mar 24 '24 09:03 vitalije

Thank you for taking the time to do that.

Based on 2 and 3, I'm fairly confident the issue lies in how venv and virtualenv creates the virtual environment on your system. The latter is what Poetry uses internally.

It could be a bug in venv/virtualenv or for some reason your environment might require some additional flags when creating the environment. If it is about missing flags, then Poetry could detect the scenario and work around the issue.

How did you install your python installation?

It would help significantly if this can be reproduced in a container so we can debug.

abn avatar Mar 24 '24 09:03 abn

I also run into this. Not much to add to the discussion at the moment, will update if I ever manage to solve it on my own.

FrontiniFederico avatar Apr 23 '24 17:04 FrontiniFederico

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions[bot] avatar May 24 '24 00:05 github-actions[bot]