Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python interpreter (QGIS WIndows) cannot read C libraries included in installed packages #59775

Open
2 tasks done
walking-the-talk opened this issue Dec 6, 2024 · 14 comments
Open
2 tasks done
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Python Console Python Console

Comments

@walking-the-talk
Copy link

What is the bug or the crash?

In Windows, the QGIS Python console reports that an installed python package is not functional, despite it working as expected in OSGEO4W shell. I thought it might be caused by included C libraries not being readable by QGIS python interpreter. In this case it is pyenchant which requires the libraries to be available (in subfolder of C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64).

Pyenchant has a VERBOSE_FIND function to check that the libraries are located

OSGEO4W shell and QGIS python console (same output):

>>> import enchant
pyenchant:: looking in C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: finding from prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: Prepending C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin to %PATH%
pyenchant:: loading library C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin\libenchant-2.dll
pyenchant:: setting prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64

OSGEO4W shell:

>>> enchant.list_languages()
['en_BW', 'en_AU', 'en_BZ', 'en_GB', 'en_JM', 'en_DK', 'en_HK', 'en_GH', 'en_US', 'en_ZA', 'en_ZW', 'en_SG', 'en_NZ', 'en_BS', 'en_AG', 'en_PH', 'en_IE', 'en_NA', 'en_TT', 'en_IN', 'en_NG', 'en_CA']

but QGIS python console:

>>> enchant.list_languages()
[]

QGIS python version doesn't see the spelling dictionaries, which are stored in
C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\share\enchant\hunspell

which means that pyenchant throws errors as there is no dictionary to work with...

It seems to be a QGIS issue not a pyenchant one.

This is preventing me from creating a functioning spell checker plugin for QGIS in Windows, and therefore potentially integrating spell-check functionality as a core feature...

#49934

https://plugins.qgis.org/plugins/QGISpell/

Please note that I am a QGIS user, not a developer, so please don't pile-in on my ignorance or general stupidity - I am very well aware of it already. But I would greatly appreciate help from developers who might be able to unlock this - my earlier attempts have led to dead-ends, probably because I don't know the right question to ask.

Steps to reproduce the issue

On a Windows PC open OSGEO4W shell and install pyenchant:

pip install pyenchant
python

behaviour in OSGEO4W shell (expected):


>>> import enchant
>>> enchant.list_languages()
['en_BW', 'en_AU', 'en_BZ', 'en_GB', 'en_JM', 'en_DK', 'en_HK', 'en_GH', 'en_US', 'en_ZA', 'en_ZW', 'en_SG', 'en_NZ', 'en_BS', 'en_AG', 'en_PH', 'en_IE', 'en_NA', 'en_TT', 'en_IN', 'en_NG', 'en_CA']
>>> d=enchant.Dict("en_GB")
>>> d.check('QGIS')
False
>>> d.suggest('QGIS')
['GIST']
>>>

start qgis and open the python console

Output from Python Console:

>>> import enchant
>>> enchant.list_languages()
[]
>>> d=enchant.Dict("en_GB")
Traceback (most recent call last):
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 542, in __init__
    super().__init__()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 144, in __init__
    self._init_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 549, in _init_this
    this = self._broker._request_dict_data(self.tag)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 287, in _request_dict_data
    self._raise_error(e_str % (tag,), DictNotFoundError)
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 234, in _raise_error
    raise eclass(err.decode())
enchant.errors.DictNotFoundError: invalid tag character found

Versions

QGIS version 3.34.10-Prizren QGIS code revision 113de9e
Qt version 5.15.13
Python version 3.12.5
QGIS version 3.34.10-Prizren QGIS code revision [113de9e](https://github.com/qgis/QGIS/commit/113de9e1) Qt version 5.15.13 Python version 3.12.5

Supported QGIS version

  • I'm running a supported QGIS version according to the roadmap.

New profile

Additional context

This problem does not occur in (QGIS for) Linux providing that libenchant is installed through the package manager - as per the installation instructions for pyenchant. Which means that a Widows PC with WSL2 and Ubuntu (for example) can run pyenchant and the QGISpell plugin works...

@walking-the-talk walking-the-talk added the Bug Either a bug report, or a bug fix. Let's hope for the latter! label Dec 6, 2024
@nicogodet
Copy link
Member

This looks similar to an issue you reported yourself last year ?
#55124

@walking-the-talk
Copy link
Author

Yes, I suppose it is. I have worked out a bit more about what the problem is as you can see. But I have already gone beyond my capabilities and have been stuck for a year... I guess I can close the other one.

@walking-the-talk
Copy link
Author

Interested / intrigued to see an apparently similar issue just reported:

#59776

And specifically

"The problem seems related to how qgis-ltr-bin.exe handles the Python environment, as the sys.executable (in the QGIS python console) points to qgis-ltr-bin.exe instead of python.exe."

I have, for the sake of argument tried the same relevant 'tests':
[where you see the word pyenchant - this was pyarrow in the original post!]

Verified pyenchant Installation:
• Confirmed that pyenchant works in the OSGeo4W shell but fails in the QGIS Python console.
Checked Python Paths:
• Verified sys.executable and sys.path in the QGIS Python console, ensuring the correct Python and site-packages directories were included.
Added Missing DLLs:
• Copied pyenchant DLL files from its installation directory to the QGIS bin folder.
• Temporarily added the pyenchant directory to the PATH environment variable.
Tried Workarounds for QGIS Python Configuration:
• Manually added the pyenchant path to sys.path in the QGIS Python console.

No change.

I'm not going to be as simple minded as to suggest they are caused by the same problem, but it would be convenient if they required the same fix... I understand that spelling isn't very sxy for everyone so my identified issue not being taken seriously compared with things that get in the way of processing data. I'm trying not to get frustrated, but forgive me if I come across that way. I would rather be using QGIS than trying to fix it :-)

@m-kuhn - you deleted your comment I think, but I did use the VERBOSE_FIND - and the results are in the original post. That's why I opened this issue as it provides a better (I hope) description of the problem compared with the one I just closed that had sat unattended for a year.

I understand that spelling isn't very sxy for everyone so my identified issue is perhaps not being taken seriously compared with things that get in the way of processing data. I'm trying not to get frustrated, but forgive me if I come across that way after first suggesting the feature in August 2022 (with an outline route-map) and then creating the plugin and releasing it as a proof-of-concept (that works in Linux but not Windows). I would rather be using QGIS than trying to fix it :-) But rather than just complain, I'm prepared to help if I can, and I appreciate assistance that is offered, to make QGIS better.

@m-kuhn
Copy link
Member

m-kuhn commented Dec 7, 2024

Yes, I realized you already reported that you've checked VERBOSE_FIND, so I removed that comment.

I would look into the enchant init code (stacktrace) and possibly add some debug statements and compare what happens in the osgeo shell case and what in the qgis py console case.

@agiudiceandrea agiudiceandrea added the Python Console Python Console label Dec 7, 2024
@agiudiceandrea
Copy link
Contributor

agiudiceandrea commented Dec 7, 2024

@walking-the-talk I guess this issue is not related to #59776.
Maybe @jef-n can have some clues on why the pyenchant Python module (installed via pip install) works in the OSGeo4W Shell, while it doesn't work in the QGIS Python Console.

@walking-the-talk
Copy link
Author

I would look into the enchant init code (stacktrace) and possibly add some debug statements and compare what happens in the osgeo shell case and what in the qgis py console case.

Thanks for this suggestion @m-kuhn - I'm not sure if this is what you meant: I used traceback in init.py and placed a call in def __init__(self): def _check_this(self, msg=None): and def list_dicts(self):

I have left VERBOSE_FIND = True (first 5 lines in each)

OSGEO4W shell:

C:\OSGeo4W>python
Python 3.12.5 (main, Aug  8 2024, 11:21:54) [MSC v.1938 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import enchant
pyenchant:: looking in C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: finding from prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: Prepending C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin to %PATH%
pyenchant:: loading library C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin\libenchant-2.dll
pyenchant:: setting prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 146, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 224, in __init__
    super().__init__()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 907, in <module>
    _broker = Broker()
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<stdin>", line 1, in <module>

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 153, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 224, in __init__
    super().__init__()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 907, in <module>
    _broker = Broker()
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<stdin>", line 1, in <module>

>>> enchant.list_languages()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 160, in _check_this
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 412, in list_dicts
    self._check_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 442, in list_languages
    for (tag, prov) in self.list_dicts():
  File "<stdin>", line 1, in <module>

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 416, in list_dicts
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 442, in list_languages
    for (tag, prov) in self.list_dicts():
  File "<stdin>", line 1, in <module>

['en_BW', 'en_AU', 'en_BZ', 'en_GB', 'en_JM', 'en_DK', 'en_HK', 'en_GH', 'en_US', 'en_ZA', 'en_ZW', 'en_SG', 'en_NZ', 'en_BS', 'en_AG', 'en_PH', 'en_IE', 'en_NA', 'en_TT', 'en_IN', 'en_NG', 'en_CA']
>>> d=enchant.Dict("en_GB")
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 146, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 563, in __init__
    super().__init__()
  File "<stdin>", line 1, in <module>

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 160, in _check_this
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 298, in _request_dict_data
    self._check_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 570, in _init_this
    this = self._broker._request_dict_data(self.tag)
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 152, in __init__
    self._init_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 563, in __init__
    super().__init__()
  File "<stdin>", line 1, in <module>

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 153, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 563, in __init__
    super().__init__()
  File "<stdin>", line 1, in <module>

Compare with QGIS Console:

import enchant
pyenchant:: looking in C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: finding from prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: Prepending C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin to %PATH%
pyenchant:: loading library C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin\libenchant-2.dll
pyenchant:: setting prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 146, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 224, in __init__
    super().__init__()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 907, in <module>
    _broker = Broker()
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "C:\OSGeo4W/apps/qgis-ltr/./python\qgis\utils.py", line 892, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 351, in keyPressEvent
    super().keyPressEvent(e)

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 153, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 224, in __init__
    super().__init__()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 907, in <module>
    _broker = Broker()
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "C:\OSGeo4W/apps/qgis-ltr/./python\qgis\utils.py", line 892, in _import
    mod = _builtin_import(name, globals, locals, fromlist, level)
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 351, in keyPressEvent
    super().keyPressEvent(e)

enchant.list_languages()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 160, in _check_this
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 412, in list_dicts
    self._check_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 442, in list_languages
    for (tag, prov) in self.list_dicts():
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 351, in keyPressEvent
    super().keyPressEvent(e)

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 416, in list_dicts
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 442, in list_languages
    for (tag, prov) in self.list_dicts():
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 351, in keyPressEvent
    super().keyPressEvent(e)

[]
d=enchant.Dict("en_GB")
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 146, in __init__
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 563, in __init__
    super().__init__()
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 351, in keyPressEvent
    super().keyPressEvent(e)

  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 160, in _check_this
    summary = traceback.StackSummary.extract(
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 298, in _request_dict_data
    self._check_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 570, in _init_this
    this = self._broker._request_dict_data(self.tag)
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 152, in __init__
    self._init_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 563, in __init__
    super().__init__()
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 351, in keyPressEvent
    super().keyPressEvent(e)

Traceback (most recent call last):
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 563, in __init__
    super().__init__()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 152, in __init__
    self._init_this()
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 570, in _init_this
    this = self._broker._request_dict_data(self.tag)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 303, in _request_dict_data
    self._raise_error(e_str % (tag,), DictNotFoundError)
  File "C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py", line 249, in _raise_error
    raise eclass(default)
enchant.errors.DictNotFoundError: Dictionary for language 'en_GB' could not be found
Please check https://pyenchant.github.io/pyenchant/ for details

I understand what it's doing, but I have no idea what it means.

@walking-the-talk
Copy link
Author

@m-kuhn - I have done as requested, so wonder if you or anyone else might have any clues from that, or advice on how better to describe the issue / bug-trace.

To my untrained eye it looks like QGIS python interpreter can locate the libraries, but pyenchant cannot then access the Dictionaries, which are in the same path - I don't know whether locating the libraries is the same as allowing pyenchant (or the python interpreter) to utilise them. Like I said before I'm beyond my competence but willing to help...

@jef-n - your input on the difference in behaviour in OSGEO4W shell and the QGIS python interpreter could be key to this. There are MinGW packages available for Enchant but I don't know how to utilise them. If they could be incorporated into the QGIS installation process for Windows would that circumvent the problem? Is there a way to simulate that on my pc to test the idea (I would need very clear instructions as I am not familiar with compilers)

Many thanks in anticipation of your help.

@m-kuhn
Copy link
Member

m-kuhn commented Dec 15, 2024

Sorry, I don't know the internals of enchant.
I would add a few debug print statements that will reveal the path being used to load the files in C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\__init__.py.

@walking-the-talk
Copy link
Author

I am struggling to stay afloat here, but I've been swimming through the code and it looks like init.py is calling _enchant.py to do the linkages to the C libraries. I have checked in that file and (lack of) error reports indicates that the module can actually find the C library (the VERBOSE output previously posted shows that positively too).

pyenchant:: looking in C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: finding from prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64
pyenchant:: Prepending C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin to %PATH%
pyenchant:: loading library C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64\bin\libenchant-2.dll
pyenchant:: setting prefix C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64

I debug-printed the paths in _enchant and can also confirm that pyenchant is using 'from_package' - which I take it means that it is using the C Libraries from the site_packages rather than looking elsewhere:

this_path:  C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant ; 
subdir:  mingw64 ; 
data_path C:\OSGeo4W\apps\Python312\Lib\site-packages\enchant\data\mingw64

Pyenchant works in QGIS running on Ubuntu natively and WSL2, it also works in another python environment on my PC with Jupyter lab and a Windows Shell (both versions of Python - 3.9.12 and 3.12.5). And of course in the OSGEO4W shell with python 3.12.5 that QGIS runs...

I am unable to produce anything that differentiates between the QGIS interpreter and the shell that relates to pyenchant but it does show (as in the previous post), which might be where the problem lie:

  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "C:\OSGeo4W\apps\Python312\Lib\code.py", line 74, in runsource
    self.runcode(code)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 251, in runsource
    return super(PythonInterpreter, self).runsource(source, filename, symbol)
  File "C:\OSGeo4W/apps/qgis-ltr/./python\console\console_sci.py", line 228, in execCommandImpl
    res = self.runsource(src)

The evidence I have gathered to date still points to the QGIS python interpreter, not pyenchant, and I have no idea how to help further. I have spent many hours chasing my tail, not being competent in this area but trying to help find clues. I am unable to make any more sensible contribution to this. I genuinely need help at a more fundamental level than trying to debug someone else's package(s). Please tell me I'm wrong on this. I think all I have revealed is my incompetence.

But perhaps it would similar to asking a member of the public to fly a plane to Australia - they might make a reasonable passenger, but you wouldn't want them in the front seat.

@m-kuhn
Copy link
Member

m-kuhn commented Dec 15, 2024

Did you open an issue on enchant side too?

For the enchant community it will be easier to guess assumptions made within enchant library which may not be met when qgis loads its python interpreter. Or unlock additional levels of debug information.

@jef-n
Copy link
Member

jef-n commented Dec 15, 2024

Is the GRASS plugin/provider installed and/or loaded? That comes with libiconv-2.dll and libintl-8.dll too - those might be incompatible with the ones shipped with pyenchant.

@walking-the-talk
Copy link
Author

@m-kuhn : Enchant issue:
pyenchant/pyenchant#311

@jef-n , I disabled the GRASS8 and GRASS GIS provider plug-ins on the clean QGIS profile I have been testing with - no change in behaviour (restarted before testing).

pyenchant has libiconv-2.dll version 1.16 and libintl-8.dll version 0.19.8.1 included in the mingw/bin folder

This is the full copy of the QGIS installation details

<style type="text/css"> p, li { white-space: pre-wrap; } </style>
QGIS version 3.34.10-Prizren QGIS code revision 113de9e
Qt version 5.15.13
Python version 3.12.5
GDAL/OGR version 3.9.2
PROJ version 9.4.0
EPSG Registry database version v11.004 (2024-02-24)
GEOS version 3.12.2-CAPI-1.18.2
SQLite version 3.45.1
PDAL version 2.6.3
PostgreSQL client version 16.2
SpatiaLite version 5.1.0
QWT version 6.2.0
QScintilla2 version 2.14.1
OS version Windows 10 Version 2009
       
Active Python plugins
db_manager 0.1.20
MetaSearch 0.3.6
processing 2.12.99
QGIS version 3.34.10-Prizren QGIS code revision [113de9e](https://github.com/qgis/QGIS/commit/113de9e1) Qt version 5.15.13 Python version 3.12.5 GDAL/OGR version 3.9.2 PROJ version 9.4.0 EPSG Registry database version v11.004 (2024-02-24) GEOS version 3.12.2-CAPI-1.18.2 SQLite version 3.45.1 PDAL version 2.6.3 PostgreSQL client version 16.2 SpatiaLite version 5.1.0 QWT version 6.2.0 QScintilla2 version 2.14.1 OS version Windows 10 Version 2009

Active Python plugins
db_manager
0.1.20
MetaSearch
0.3.6
processing
2.12.99

@jef-n
Copy link
Member

jef-n commented Dec 15, 2024

The mingw dlls shipped with pyenchant are older, than the ones with GRASS (uninstalling GRASS or renaming the grass directory makes enchant load)

@walking-the-talk
Copy link
Author

@jef-n thanks for updating your comment, much more helpful - however, I'm afraid I can't replicate that: if I rename the GRASS folders (in both OSGEO4W and qgis-ltr folders to make sure) I am unable to change the outcome of previous tests.

after import enchant the enchant.list_languages() still provides an empty list.

For the sake of curiosity, I copied the five dlls that overlap between GRASS and enchant into the mingw/bin folder to see if that helped. It didn't - same result an empty list of languages in the QGIS console, and a full language list in OSGEO4W shell - at least it didn't break enchant though. So maybe it was an outdated packaging thing rather than a dependency on a particular version of the dlls.

enchant-grass-compare

The pyenchant docs do outline a different way to install on Windows, 'taking advantage of mingw', but I was unable to complete this task as the the devil is in the detail: https://pyenchant.github.io/pyenchant/install.html#using-mingw - I don't have the skills / capacity to learn how to do this. Which also means I don't know the implications of trying to get the mingw package of enchant https://packages.msys2.org/packages/mingw-w64-x86_64-enchant incorporated into OSGEO4W - that's the reason I haven't filed a request - it might be a completely unreasonable one.

Maybe I've wasted 18 months by trying to get pyenchant to work on windows and I shouldn't have started from here - it seemed like a good idea at the time. I am actively trying to improve QGIS rather than just complaining about things not working as I would like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Either a bug report, or a bug fix. Let's hope for the latter! Python Console Python Console
Projects
None yet
Development

No branches or pull requests

5 participants