Correct add site-packages folder to Sublime Text 3

2019-07-11 03:52发布

1. Summary

I don't understand, how I can make, that global site-packages path will add to Sublime Text 3 sys.path in each Sublime Text 3 start.


2. Reason

I want, that in Sublime Text plugins would be possible use globally installed packages.

See more in Global Python packages in Sublime Text plugin development question.


3. Example

Example part of my plugin:

import os
import sublime_plugin
import sys

from duckduckgo import query  # noqa
from pygoogling.googling import GoogleSearch  # noqa

# Any actions

Where duckduckgo and pygoogling.googling — Python modules from site-packages folder.

Real plugin example.


4. Not helped

4.1. Manually add path to console

I open Sublime Text console → I paste to it:

import sys; sys.path.append('C:\Python36\Lib\site-packages')

Now:

>>> sys.path
['D:\\Sublime Text Build 3143 x64 For Debug', 'D:\\Sublime Text Build 3143 x64 For Debug\\python3.3.zip', 'D:\\Sublime Text Build 3143 x64 For Debug\\Data\\Lib\\python3.3', 'D:\\Sublime Text Build 3143 x64 For Debug\\Data\\Packages', 'C:\\Python36\\Lib\\site-packages']

I restart Sublime Text → I open Sublime Text console:

>>> import sys; sys.path
['D:\\Sublime Text Build 3143 x64 For Debug', 'D:\\Sublime Text Build 3143 x64 For Debug\\python3.3.zip', 'D:\\Sublime Text Build 3143 x64 For Debug\\Data\\Lib\\python3.3', 'D:\\Sublime Text Build 3143 x64 For Debug\\Data\\Packages']

Environment variables, added manually, clean after each restart.

4.2. Using PYTHONPATH

My PYTHONPATH user variable in interpreter:

>>> import sys; sys.path
['', 'C:\\Python36', 'C:\\Python36\\python36.zip', 'C:\\Python36\\DLLs', 'C:\\Python36\\lib', 'C:\\Python36\\lib\\site-packages']

I modify my plugin:

import os
import sublime_plugin
import sys

sys.path.append((os.environ['PYTHONPATH']))

from duckduckgo import query  # noqa
from pygoogling.googling import GoogleSearch  # noqa

# Any actions

Now:

>>> import sys; sys.path
['D:\\Sublime Text Build 3143 x64 For Debug', 'D:\\Sublime Text Build 3143 x64 For Debug\\python3.3.zip', 'D:\\Sublime Text Build 3143 x64 For Debug\\Data\\Lib\\python3.3', 'D:\\Sublime Text Build 3143 x64 For Debug\\Data\\Packages', 'C:\\Python36']

But Sublime Text doesn't accept modules from site-packages:

reloading plugin KristinitaLuckyLink.KristinitaLuckyLink
Traceback (most recent call last):
  File "D:\Sublime Text Build 3143 x64 For Debug\sublime_plugin.py", line 109, in reload_plugin
    m = importlib.import_module(modulename)
  File "./python3.3/importlib/__init__.py", line 90, in import_module
  File "<frozen importlib._bootstrap>", line 1584, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1565, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1532, in _find_and_load_unlocked
  File "D:\Sublime Text Build 3143 x64 For Debug\sublime_plugin.py", line 915, in load_module
    exec(compile(source, source_path, 'exec'), mod.__dict__)
  File "D:\Sublime Text Build 3143 x64 For Debug\Data\Packages\KristinitaLuckyLink\KristinitaLuckyLink.py", line 40, in <module>
    from duckduckgo import query  # noqa
ImportError: No module named 'duckduckgo'

4.3. site-packages environment variable

I modify my plugin as in Anthony Perrot answer:

import os
import sublime_plugin
import sys

python_environment_variable = (os.environ['PYTHONPATH'])
sys.path.append(python_environment_variable)

site_packages = next(p for p in python_environment_variable if 'site-packages' in p)
sys.path.append(site_packages)

from duckduckgo import query  # noqa
from pygoogling.googling import GoogleSearch  # noqa

# Any actions

I get StopIteration exception in console:

reloading plugin KristinitaLuckyLink.KristinitaLuckyLink
Traceback (most recent call last):
  File "D:\Sublime Text Build 3143 x64 For Debug\sublime_plugin.py", line 109, in reload_plugin
    m = importlib.import_module(modulename)
  File "./python3.3/importlib/__init__.py", line 90, in import_module
  File "<frozen importlib._bootstrap>", line 1584, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1565, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1532, in _find_and_load_unlocked
  File "D:\Sublime Text Build 3143 x64 For Debug\sublime_plugin.py", line 915, in load_module
    exec(compile(source, source_path, 'exec'), mod.__dict__)
  File "D:\Sublime Text Build 3143 x64 For Debug\Data\Packages\KristinitaLuckyLink\KristinitaLuckyLink.py", line 36, in <module>
    site_packages = next(p for p in python_environment_variable if 'site-packages' in p)
StopIteration

5. Worked, but unexpected

5.1. Working example

I add new environment variable to my operating system, for example:

PYTHONPACKAGES=C:\Python36\Lib\site-packages

Where:

And modify my plugin:

import os
import sublime_plugin
import sys

sys.path.append((os.environ['PYTHONPACKAGES']))

from duckduckgo import query  # noqa
from pygoogling.googling import GoogleSearch  # noqa

# Any actions

Plugin will successful works.

5.2. Reason, why unexpected

Each user, who will download my plugin, need add PYTHONPACKAGES environment variable for operating system and, possibly, restart operating system.

It would be nice, if would be possible, that users of plugin don't need add environment variables.

Expected behavior: user install plugin → user can work with plugin without additional actions of setting up.


6. Do not offer

  1. Please, do not offer, that I don't need to use global modules and I need to integrate external modules to plugin folder.

1条回答
在下西门庆
2楼-- · 2019-07-11 04:16

You can also do this using the following:

import site

# if outside of a sublime text plugin class
all_views = sublime.active_window().views()
# or if inside use the 'view' variable, skip to line 9 and change 
# all_views[0].settings to view.settings

if len(all_views) > 0:
    external_python_path = all_views[0].settings().get("external_python_path")

    sp = site.getsitepackages(external_python_path)
    sp = [x for x in sp if "site-packages" in x.lower()]
    sys.path.append(sp)

then in your Preferences.sublime-settings file, you add a key:value like

{
    "somekey": "somevalue",
    ...,
    "external_python_path": "path_to_python folder excluding the python.exe"
}
查看更多
登录 后发表回答