簡體   English   中英

Sublime Text插件開發中的全局Python包

[英]Global Python packages in Sublime Text plugin development

1.總結

我沒有發現,Sublime Text插件開發人員如何使用Sublime Text查找全局Python包,而不是Sublime Text目錄的Python包。

Sublime Text使用自己的Python環境,而不是機器的Python環境。 開發人員需要sys.path來設置不是內置的Sublime Text Python包。

是否有任何方法,在Sublime Text插件中使用全局安裝的Python包? 例如,如果有人告訴我,如何更改我的插件,那將是很好的 - 請參閱此問題的3.2項。


2.使用Sublime Text 3環境的缺點

  1. Sublime Text 3 Build 3126使用Python 3.3,但在撰寫本期時,發布Python 3.6穩定版。 Python 3.6有更多功能。
  2. 開發人員需要添加和更新第三方Python包,即使是為用戶安裝的也是如此。 它花了一些時間的開發人員。
  3. 對於開發人員,可能存在包的依賴性問題,請參閱此問題的6.2項。

3.例子

1. Python代碼

例如,我編寫了Python代碼 - 將Поиск Кристиниты替換為[**Поиск Кристиниты**](https://github.com/Kristinita/Kristinita.github.io) ,其中https://github.com/Kristinita/Kristinita.github.io - DuckDuckGo查詢Поиск Кристиниты第一個鏈接。

# -*- coding: utf-8 -*-
import re
import urllib

from bs4 import BeautifulSoup

from w3lib.url import safe_url_string


# ASCII link for solved encoding problems —
# https://stackoverflow.com/a/40654295/5951529
ascii_link = safe_url_string(
    u'http://duckduckgo.com/html/?q=' + 'Поиск Кристиниты',
    encoding="UTF-8")
print(ascii_link)
# SERP DuckDuckGo
serp = urllib.request.urlopen(ascii_link)
# Reading SERP
read_serp = serp.read()
# BeautifulSoup — https://stackoverflow.com/a/11923803/5951529
parsed = BeautifulSoup(read_serp, "lxml")
# Parsed first link
first_link = parsed.findAll(
    'div', {'class': re.compile('links_main*')})[0].a['href']
# Remove DuckDuckGo specific characters —
# https://stackoverflow.com/a/3942100/5951529
remove_duckduckgo_symbols = first_link.replace("/l/?kh=-1&uddg=", "")
# https://stackoverflow.com/a/32451970/5951529
final_link = (urllib.parse.unquote(remove_duckduckgo_symbols))
# Markdown link
markdown_link = '[' + 'Поиск Кристиниты' + ']' + \
    '(' + final_link + ')'

print(markdown_link)

如果我在終端或SublimeREPL中運行此文件,我會輸入:

[**Поиск Кристиниты**](https://github.com/Kristinita/Kristinita.github.io/)

2. Sublime Text插件

現在,基於這段代碼,我編寫了Sublime Text插件,用於將example text替換為[**example text**](http://<first link for DuckDuckGo query “example link”>)

import re
import urllib

from bs4 import BeautifulSoup

from w3lib.url import safe_url_string

import sublime_plugin


class KristinitaLuckyLinkCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        # Get selection text
        print('KristinitaLuckyLink called')
        select = self.view.sel()
        selection_region = select[0]
        selection_text = self.view.substr(selection_region)
        print(selection_text)

        # ASCII link for solved encoding problems —
        # https://stackoverflow.com/a/40654295/5951529
        ascii_link = safe_url_string(
            u'http://duckduckgo.com/html/?q=' + (selection_text),
            encoding="UTF-8")
        print(ascii_link)
        # SERP DuckDuckGo
        serp = urllib.request.urlopen(ascii_link)
        # Reading SERP
        read_serp = serp.read()
        # BeautifulSoup — https://stackoverflow.com/a/11923803/5951529
        parsed = BeautifulSoup(read_serp, "lxml")
        # Parsed first link
        first_link = parsed.findAll(
            'div', {'class': re.compile('links_main*')})[0].a['href']
        # Remove DuckDuckGo specific characters —
        # https://stackoverflow.com/a/3942100/5951529
        remove_duckduckgo_symbols = first_link.replace("/l/?kh=-1&uddg=", "")
        # Final link — https://stackoverflow.com/a/32451970/5951529
        final_link = (urllib.parse.unquote(remove_duckduckgo_symbols))
        markdown_link = '[' + selection_text + ']' + \
            '(' + final_link + ')'
        print(markdown_link)

        # Replace selected text to Markdown link
        self.view.replace(
            edit, selection_region, markdown_link)

4.預期的行為

如果用戶已安裝Python並安裝包

  • pip install beautifulsoup4
  • pip install lxml
  • pip install w3lib

我想,我的2.2項目的插件成功為用戶工作。


5.實際行為

如果我保存我的插件,我會得到堆棧跟蹤:

Traceback (most recent call last):
  File "D:\Sublime Text Build 3126 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 "<frozen importlib._bootstrap>", line 584, in _check_name_wrapper
  File "<frozen importlib._bootstrap>", line 1022, in load_module
  File "<frozen importlib._bootstrap>", line 1003, in load_module
  File "<frozen importlib._bootstrap>", line 560, in module_for_loader_wrapper
  File "<frozen importlib._bootstrap>", line 868, in _load_module
  File "<frozen importlib._bootstrap>", line 313, in _call_with_frames_removed
  File "D:\Sublime Text Build 3126 x64 For Debug\Data\Packages\Grace Splitter\kristi.py", line 4, in <module>
    from bs4 import BeautifulSoup
ImportError: No module named 'bs4'

6.沒有幫助

1.使用計算機的全局Python環境

我沒有找到,我怎么做。 我可以找到的問題示例:

2.使用Sublime Text環境

我安裝

我將我的w3lib目錄從C:\\Python36\\Lib\\site-packages復制到Sublime Text的Data\\Packages目錄。

我在Sublime Text 3控制台中運行:

>>> window.run_command("kristinita_lucky_link")

我得到堆棧跟蹤:

Traceback (most recent call last):
  File "D:\Sublime Text 3 x64\sublime_plugin.py", line 818, in run_
    return self.run(edit)
  File "D:\Sublime Text 3 x64\Data\Packages\KristinitaLuckyLink\KristinitaLuckyLink.py", line 32, in run
    parsed = BeautifulSoup(read_serp, "lxml")
  File "D:\Sublime Text 3 x64\Data\Packages\bs4\__init__.py", line 165, in __init__
    % ",".join(features))
bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

我沒有找到,我怎么能設置lxml

3.在2個文件中使用變量

比如我有KristinitaLuckyLink.pyKrisDuckDuckGo.py在同一個目錄中的文件。

我的KristinitaLuckyLink.py文件:

import re
import requests
import sublime_plugin
import subprocess
import sys
sys.path.append(
    'D:\Sublime Text 3 x64\Data\Packages\KristinitaLuckyLink\KrisDuckDuckGo.py')

from KrisDuckDuckGo import final_link
from bs4 import BeautifulSoup


class KristinitaLuckyLinkCommand(sublime_plugin.TextCommand):

    def run(self, edit):
        # Get selection text
        print('KristinitaLuckyLink called')
        select = self.view.sel()
        selection_region = select[0]
        selection_text = self.view.substr(selection_region)
        print(selection_text)

        # Get terminal output — https://stackoverflow.com/a/4760517/5951529
        # Paths is correct
        result = subprocess.run(["C:\Python36\python.exe", "D:\Sublime Text 3 x64\Data\Packages\KristinitaLuckyLink\krisduckduckgo.py"],
                                stdout=subprocess.PIPE)
        final_link = result.stdout.decode('utf-8')
        print(final_link)

        # Markdown link
        markdown_link = '[' + selection_text + ']' + \
            '(' + final_link + ')'
        print(markdown_link)

        # Replace selected text to Markdown link
        self.view.replace(
            edit, selection_region, markdown_link)

我的KrisDuckDuckGo.py文件:

import urllib

import sys
sys.path.append(
    'D:\Sublime Text 3 x64\Data\Packages\KristinitaLuckyLink\KristinitaLuckyLink.py')

from w3lib.url import safe_url_string

from KristinitaLuckyLink import selection_text

from bs4 import BeautifulSoup


# ASCII link for solved encoding problems —
# https://stackoverflow.com/a/40654295/5951529
ascii_link = safe_url_string(
    u'http://duckduckgo.com/html/?q=' + (selection_text),
    encoding="UTF-8")
print(ascii_link)
# SERP DuckDuckGo
serp = urllib.request.urlopen(ascii_link)
# Reading SERP
read_serp = serp.read()
# BeautifulSoup — https://stackoverflow.com/a/11923803/5951529
parsed = BeautifulSoup(read_serp, "lxml")
# Parsed first link
first_link = parsed.findAll(
    'div', {'class': re.compile('links_main*')})[0].a['href']
# Remove DuckDuckGo specific characters —
# https://stackoverflow.com/a/3942100/5951529
remove_duckduckgo_symbols = first_link.replace("/l/?kh=-1&uddg=", "")
# Final link — https://stackoverflow.com/a/32451970/5951529
final_link = (urllib.parse.unquote(remove_duckduckgo_symbols))
print(final_link)

我選擇任何文本→我在Sublime Text控制台中打印:

window.run_command( “kristinita_lucky_link”)

我沒有在Sublime Text控制台中獲得輸出。


7.環境

操作系統和版本:
Windows 10企業版LTSB 64位EN
崇高文字:
建立3126
蟒蛇:
3.6.0

如果您想在計算機上使用Python版本(Sublime不提供),您可以使用以下Sublime命令:

window.run_command("exec", {"shell_cmd" : '<your command here>'})

此命令允許您在Sublime之外的計算機上執行應用程序。 只需將<your command here>替換為您要執行的shell命令即可。 輸出將在sublime的輸出面板(終端)中返回。 該輸出面板與Sublime控制台不同。

您可以將要使用的本地Python的路徑放在那里,並使用腳本(需要額外的Python模塊)作為參數。 例如:

window.run_command("exec", {"shell_cmd" : 'C:\\Python36\\python.exe D:\\Sublime Text 3 x64\\Data\\Packages\\KristinitaLuckyLink\\LuckyLink\\LuckyLink.py'})

您需要將包拆分為兩個文件。 一個文件,描述您的包和Sublime內部所需的命令。 另一個文件(應該位於程序包目錄的子目錄中 - 因此Sublime不作為插件處理)包含其余的代碼。 第二個文件是導入未包含在Sublime內部Python中的Python模塊的位置。 此外,您需要找到一種方法將您想要使用的選擇或字符串/ URL轉移到第二個腳本。

您可以在我的Sublime包PlotGraph中查看我是如何做到的

錯誤:

bs4.FeatureNotFound: Couldn't find a tree builder with the features you requested: lxml. Do you need to install a parser library?

很可能是因為Sublime Text發現lxml是作為全局Python環境的一部分安裝的 - 它是為不同版本的Python編譯而不是ST使用的 - 所以它無法加載它。

我們想要的是讓ST找到你在問題中鏈接的sublime-lxml依賴項。 “你為什么找錯了?”,你可能會問。 很難說肯定,但我認為OdatNurd的回答給了我們一些線索 - 由於某種原因ST看到的sys.path包括你所有的全局Python包。 默認情況下,ST應該只使用其可執行文件所在的文件夾和ST數據目錄中的Packages文件夾。 例如,在我的系統上,執行import sys; sys.path ST的控制台中的import sys; sys.path給了我:

[
 'C:\\Program Files\\Sublime Text 3',
 'C:\\Program Files\\Sublime Text 3/python3.3.zip',
 'C:\\Users\\Keith\\AppData\\Roaming\\Sublime Text 3\\Packages',
 'C:\\Users\\Keith\\AppData\\Roaming\\SUBLIM~1\\Packages\\lxml\\ST3_WI~2'
]

即沒有site-packages文件夾。

因此解決方案是:

一種。 您可以嘗試卸載系統范圍的lxml軟件包,以便ST只能找到sublime-lxml依賴軟件包,但實際上這只是一個臨時措施。 最好是:b。 調整ST正在使用的路徑環境變量(項目的順序)。 (即刪除對site-packages所有引用,或者至少移動它們以便它們位於ST文件夾之后。)

選項B不應該影響任何其他ST插件,因為它們也會遇到同樣的問題。 我懷疑其他一些軟件包改變了ST正在使用的路徑,但是可能不容易找出哪一個,而不是全部搜索它們。 使用構建系統時,用於那些的路徑與插件用於加載其模塊的路徑完全不同,因此構建系統也應該不受此“修復”的影響。

Python通過sys.path從它知道的位置加載模塊,在Sublime Text 3中, sys.path僅指向幾個位置(例如Sublime可執行文件附帶的軟件包的位置,當前用戶的用戶安裝軟件包的位置)等)。

要從Sublime文本插件中訪問全局安裝的Python模塊,您需要從插件中將其位置顯式添加到sys.path

假設一台Linux機器的python軟件包安裝在/usr/local/lib/python3.4/site-packages (將其修改為適用於Windows機器的適當路徑),其示例如下:

import sublime
import sublime_plugin
import sys

site_path="/usr/local/lib/python3.4/site-packages"
if site_path not in sys.path:
    sys.path.append(site_path)

from bs4 import BeautifulSoup

class ExampleCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        parser = BeautifulSoup('<a href="#">Link Text</a>', "html.parser")
        a = parser.find("a")
        text = a.contents[0]
        self.view.insert(edit, 0, text)

這特別添加了sys.path的路徑(如果它尚不存在),允許導入和使用模塊。

Sublime包含自己獨特的Python版本,專門用於沙盒本身,因此它根本不依賴於任何版本的python或正在用於運行它的計算機上安裝的任何python包,這就是為什么它不這樣做對你默認。

是的,插件可以與Python模塊一起使用,用戶可以全局安裝。 您沒有義務向Sublime Text插件介紹模塊。

問題

1. Python 3.3兼容性

對於 2018年開始:

您在插件中使用的所有全局模塊都必須與Python 3.3兼容。

1.1。 論證

1.1.1。 Sublime Text sys.path命令

例如,我添加到Default.sublime-package存檔文件0000.py Default.sublime-package中的模塊首先由Sublime Text start 加載

0000.py內容:

import sys

sys.path.append('C:\\Python36')
sys.path.append('C:\\Python36\\python36.zip')
sys.path.append('C:\\Python36\\DLLs')
sys.path.append('C:\\Python36\\lib')
sys.path.append('C:\\Python36\\lib\\site-packages')

路徑 - 我的全局sys.path

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

我重新啟動Sublime Text→我在控制台中看到:

DPI scale: 1
startup, version: 3143 windows x64 channel: stable
executable: /D/Sublime Text Build 3143 x64 For Debug/sublime_text.exe
working dir: /D/Kristinita
packages path: /D/Sublime Text Build 3143 x64 For Debug/Data/Packages
state path: /D/Sublime Text Build 3143 x64 For Debug/Data/Local
zip path: /D/Sublime Text Build 3143 x64 For Debug/Packages
zip path: /D/Sublime Text Build 3143 x64 For Debug/Data/Installed Packages
ignored_packages: ["Anaconda", "Vintage"]
pre session restore time: 0.458819
startup time: 0.493818
first paint time: 0.506818
reloading plugin Default.0000
reloading plugin Default.auto_indent_tag
reloading plugin Default.block
# And so on
>>> 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', 'C:\\Python36\\python36.zip', 'C:\\Python36\\DLLs', 'C:\\Python36\\lib', 'C:\\Python36\\lib\\site-packages']

來自內部環境的路徑在前方,即全球環境中的路徑。 我不知道,我怎么能改變它。

1.1.2。 Python 3.6模塊

例如,我想在我的插件Python Google Search API PyPI模塊中使用。 它與Python 3.6兼容,但與Python 3.3不兼容

我按照上面的小節注入文件0000.py →我創建插件SashaGSearch.py ,它內容:

import sublime_plugin

from gsearch.googlesearch import search


class GoogleSearchCommand(sublime_plugin.TextCommand):

    def run(self, edit):

        results = search('kristinitaluckylife', num_results=1)
        r = results[0][1]
        print(r)

我重新啟動Sublime Text→我得到相同的回溯 ,就像0000.py沒有實現一樣。

1.2。 2018年初的情況

請參閱Sublime Text論壇討論:

我希望,在內部Sublime Text環境中,Python 3.3將在最近的將來被替換為3.6或下一個3.7版本。


2.環境變量

如果您知道,那可能不添加新的環境變量,請回答這個問題

2.1。 插件代碼

您需要在您的PC環境變量上創建值 - 路徑到site-packages文件夾。 例如,我將其命名為PYTHONPACKAGES

您需要添加到代碼行,如OdatNurd答案

# PYTHONPACKAGES path:
# https://stackoverflow.com/a/4907053/5951529
# Disable duplicate paths:
# https://stackoverflow.com/a/42656754/5951529
site_packages = (os.environ['PYTHONPACKAGES'])
if site_packages not in sys.path:
    sys.path.append(site_packages)

2.2。 激活說明

您的插件用戶還必須在操作系統中添加環境變量PYTHONPACKAGES 在您的包的描述中,您需要添加說明,如何做。


3.重啟

對於開發過程:

如果更改site-packages文件夾或子文件夾中的文件,則可能需要重新啟動Sublime Text。

3.1。

你可以從pip安裝examplesashamodule →你啟動Sublime Text→你將examplesashamodule導入你的插件→你從site-packages文件夾中刪除examplesashamodule →插件將作為examplesashamodule仍然在site-packages文件夾中。 在這種情況下, AutomaticPackageReloader包沒有幫助。

你重新啟動Sublime Text→你在Sublime Text控制台得到回溯,那就是ImportError: No module named 'examplesashamodule'

顯然,Sublime Text會話來自會話中外部模塊的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM