1. Introduction
This document is intended to be both a tutorial and a reference guide. While it does not list all possible use cases, it should give a good overview of the principal functionality.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section GNU Free Documentation License .
This license also applies to all code snippets in this document.
- Scripting in the Python Console
- Python Plugins
- Processing Plugins
- The startup.py file
- The PYQGIS_STARTUP environment variable
- The —code parameter
- Additional arguments for Python
- Using PyQGIS in standalone scripts
- Using PyQGIS in custom applications
- Running Custom Applications
Python support was first introduced in QGIS 0.9. There are several ways to use Python in QGIS Desktop (covered in the following sections):
- Issue commands in the Python console within QGIS
- Create and use plugins
- Automatically run Python code when QGIS starts
- Create processing algorithms
- Create functions for expressions in QGIS
- Create custom applications based on the QGIS API
Python bindings are also available for QGIS Server, including Python plugins (see QGIS Server and Python ) and Python bindings that can be used to embed QGIS Server into a Python application.
There is a complete QGIS C++ API reference that documents the classes from the QGIS libraries. The Pythonic QGIS API (pyqgis) is nearly identical to the C++ API.
Another good resource for learning how to perform common tasks is to download existing plugins from the plugin repository and examine their code.
1.1. Scripting in the Python Console
QGIS provides an integrated Python console for scripting. It can be opened from the Plugins ► Python Console menu:

The screenshot above illustrates how to get the layer currently selected in the layer list, show its ID and optionally, if it is a vector layer, show the feature count. For interaction with the QGIS environment, there is an iface variable, which is an instance of QgisInterface . This interface allows access to the map canvas, menus, toolbars and other parts of the QGIS application.
For user convenience, the following statements are executed when the console is started (in the future it will be possible to set further initial commands)
from qgis.core import * import qgis.utils
For those which use the console often, it may be useful to set a shortcut for triggering the console (within Settings ► Keyboard shortcuts… )
1.2. Python Plugins
The functionality of QGIS can be extended using plugins. Plugins can be written in Python. The main advantage over C++ plugins is simplicity of distribution (no compiling for each platform) and easier development.
Many plugins covering various functionality have been written since the introduction of Python support. The plugin installer allows users to easily fetch, upgrade and remove Python plugins. See the Python Plugins page for more information about plugins and plugin development.
Creating plugins in Python is simple, see Developing Python Plugins for detailed instructions.
Python plugins are also available for QGIS server. See QGIS Server and Python for further details.
1.2.1. Processing Plugins
Processing Plugins can be used to process data. They are easier to develop, more specific and more lightweight than Python Plugins. Writing a Processing plugin explains when the use of Processing algorithms is appropiate and how to develop them.
1.3. Running Python code when QGIS starts
There are different methods to run Python code every time QGIS starts.
- Creating a startup.py script
- Setting the PYQGIS_STARTUP environment variable to an existing Python file
- Specifying a startup script using the —code init_qgis.py parameter.
1.3.1. The startup.py file
Every time QGIS starts, the user’s Python home directory and a list of system paths are searched for a file named startup.py . If that file exists, it is executed by the embedded Python interpreter.
The path in the user’s home directory usually is found under:
- Linux: .local/share/QGIS/QGIS3
- Windows: AppData\Roaming\QGIS\QGIS3
- macOS: Library/Application Support/QGIS/QGIS3
The default system paths depend on the operating system. To find the paths that work for you, open the Python Console and run QStandardPaths.standardLocations(QStandardPaths.AppDataLocation) to see the list of default directories.
The startup.py script is executed immediately upon initializing python in QGIS, early on in the start of the application.
1.3.2. The PYQGIS_STARTUP environment variable
You can run Python code just before QGIS initialization completes by setting the PYQGIS_STARTUP environment variable to the path of an existing Python file.
This code will run before QGIS initialization is complete. This method is very useful for cleaning sys.path, which may have undesireable paths, or for isolating/loading the initial environment without requiring a virtual environment, e.g. homebrew or MacPorts installs on Mac.
1.3.3. The —code parameter
You can provide custom code to execute as startup paramteter to QGIS. To do so, create a python file, for example qgis_init.py , to execute and start QGIS from the command line using qgis —code qgis_init.py .
Code provided via —code is executed late in the QGIS initialization phase, after the application components have been loaded.
1.3.4. Additional arguments for Python
To provide additional arguments for your —code script or for other python code that is executed, you can use the —py-args argument. Any argument coming after —py-args and before a — arg (if present) will be passed to Python but ignored by the QGIS application itself.
In the following example, myfile.tif will be available via sys.argv in Python but will not be loaded by QGIS. Whereas otherfile.tif will be loaded by QGIS but is not present in sys.argv .
qgis --code qgis_init.py --py-args myfile.tif -- otherfile.tif
If you want access to every command line parameter from within Python, you can use QCoreApplication.arguments()
QgsApplication.instance().arguments()
1.4. Python Applications
It is often handy to create scripts for automating processes. With PyQGIS, this is perfectly possible — import the qgis.core module, initialize it and you are ready for the processing.
Or you may want to create an interactive application that uses GIS functionality — perform measurements, export a map as PDF, … The qgis.gui module provides various GUI components, most notably the map canvas widget that can be incorporated into the application with support for zooming, panning and/or any further custom map tools.
PyQGIS custom applications or standalone scripts must be configured to locate the QGIS resources, such as projection information and providers for reading vector and raster layers. QGIS Resources are initialized by adding a few lines to the beginning of your application or script. The code to initialize QGIS for custom applications and standalone scripts is similar. Examples of each are provided below.
Do not use qgis.py as a name for your script. Python will not be able to import the bindings as the script’s name will shadow them.
1.4.1. Using PyQGIS in standalone scripts
To start a standalone script, initialize the QGIS resources at the beginning of the script:
1from qgis.core import * 2 3# Supply path to qgis install location 4QgsApplication.setPrefixPath("/path/to/qgis/installation", True) 5 6# Create a reference to the QgsApplication. Setting the 7# second argument to False disables the GUI. 8qgs = QgsApplication([], False) 9 10# Load providers 11qgs.initQgis() 12 13# Write your code here to load some layers, use processing 14# algorithms, etc. 15 16# Finally, exitQgis() is called to remove the 17# provider and layer registries from memory 18qgs.exitQgis()
First we import the qgis.core module and configure the prefix path. The prefix path is the location where QGIS is installed on your system. It is configured in the script by calling the setPrefixPath() method. The second argument of setPrefixPath() is set to True , specifying that default paths are to be used.
The QGIS install path varies by platform; the easiest way to find it for your system is to use the Scripting in the Python Console from within QGIS and look at the output from running:
QgsApplication.prefixPath()
After the prefix path is configured, we save a reference to QgsApplication in the variable qgs . The second argument is set to False , specifying that we do not plan to use the GUI since we are writing a standalone script. With QgsApplication configured, we load the QGIS data providers and layer registry by calling the initQgis() method.
qgs.initQgis()
With QGIS initialized, we are ready to write the rest of the script. Finally, we wrap up by calling exitQgis() to remove the data providers and layer registry from memory.
qgs.exitQgis()
1.4.2. Using PyQGIS in custom applications
The only difference between Using PyQGIS in standalone scripts and a custom PyQGIS application is the second argument when instantiating the QgsApplication . Pass True instead of False to indicate that we plan to use a GUI.
1from qgis.core import * 2 3# Supply the path to the qgis install location 4QgsApplication.setPrefixPath("/path/to/qgis/installation", True) 5 6# Create a reference to the QgsApplication. 7# Setting the second argument to True enables the GUI. We need 8# this since this is a custom application. 9 10qgs = QgsApplication([], True) 11 12# load providers 13qgs.initQgis() 14 15# Write your code here to load some layers, use processing 16# algorithms, etc. 17 18# Finally, exitQgis() is called to remove the 19# provider and layer registries from memory 20qgs.exitQgis()
Now you can work with the QGIS API — load layers and do some processing or fire up a GUI with a map canvas. The possibilities are endless 🙂
1.4.3. Running Custom Applications
You need to tell your system where to search for QGIS libraries and appropriate Python modules if they are not in a well-known location — otherwise Python will complain:
>>> import qgis.core ImportError: No module named qgis.core
This can be fixed by setting the PYTHONPATH environment variable. In the following commands, should be replaced with your actual QGIS installation path:
- on Linux: export PYTHONPATH=//share/qgis/python
- on Windows: set PYTHONPATH=c:\\python
- on macOS: export PYTHONPATH=//Contents/Resources/python
Now, the path to the PyQGIS modules is known, but they depend on the qgis_core and qgis_gui libraries (the Python modules serve only as wrappers). The path to these libraries may be unknown to the operating system, and then you will get an import error again (the message might vary depending on the system):
>>> import qgis.core ImportError: libqgis_core.so.3.2.0: cannot open shared object file: No such file or directory
Fix this by adding the directories where the QGIS libraries reside to the search path of the dynamic linker:
- on Linux: export LD_LIBRARY_PATH=//lib
- on Windows: set PATH=C:\\bin;C:\\apps\\bin;%PATH% where should be replaced with the type of release you are targeting (eg, qgis-ltr , qgis , qgis-dev )
These commands can be put into a bootstrap script that will take care of the startup. When deploying custom applications using PyQGIS, there are usually two possibilities:
- require the user to install QGIS prior to installing your application. The application installer should look for default locations of QGIS libraries and allow the user to set the path if not found. This approach has the advantage of being simpler, however it requires the user to do more steps.
- package QGIS together with your application. Releasing the application may be more challenging and the package will be larger, but the user will be saved from the burden of downloading and installing additional pieces of software.
The two deployment models can be mixed. You can provide a standalone applications on Windows and macOS, but for Linux leave the installation of GIS up to the user and his package manager.
1.5. Technical notes on PyQt and SIP
We’ve decided for Python as it’s one of the most favoured languages for scripting. PyQGIS bindings in QGIS 3 depend on SIP and PyQt5. The reason for using SIP instead of the more widely used SWIG is that the QGIS code depends on Qt libraries. Python bindings for Qt (PyQt) are done using SIP and this allows seamless integration of PyQGIS with PyQt.
© Copyright 2002-now, QGIS project. Last updated on 2023 Nov 19, 09:00 +0000.
QGIS 3.4 Couldn’t load SIP module. Python support will be disabled on Windows 10
I feel that there is an issue with my Python Path but I’ve tried several things to fix it and I am not there yet. Does anyone know a fix for this?
75.1k 56 56 gold badges 237 237 silver badges 381 381 bronze badges
asked Dec 19, 2018 at 17:49
885 7 7 silver badges 19 19 bronze badges** From bad to worse after an uninstall and reinstall. ** An error occurred during execution of following code: qgis.utils.initInterface(1797760070112) Traceback (most recent call last): File «», line 1, in File «C:/PROGRA~1/QGIS3~1.4/apps/qgis/./python\qgis\utils.py», line 219, in initInterface iface = wrapinstance(pointer, QgisInterface) TypeError: wrapinstance() argument 2 must be sip.wrappertype, not sip.wrappertype Python version: 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] QGIS version: 3.4.2-Madeira ‘Madeira’, 22034aa070
Dec 20, 2018 at 13:41
I am in a vicious circle of uninstalling / installing QGIS 3.4.3 to be able to run plugins and installing PyQt5. When I uninstall both of them and reinstall QGIS i cannot build with pb_tool due to something wrong with pyrcc5 and I have to pip install PyQt5. Then I get «QGIS 3.4 Couldn’t load SIP module. Python support will be disabled on Windows 10». Is there some magic version of PyQt5 that makes this all work?
Saved searches
Use saved searches to filter your results more quickly
Cancel Create saved search
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
qgis / QGIS Public
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
Upgrade default QGIS python from 3.9 to latest stable version #54491
AmirsamanAhmadi opened this issue Sep 5, 2023 · 6 comments
Upgrade default QGIS python from 3.9 to latest stable version #54491
AmirsamanAhmadi opened this issue Sep 5, 2023 · 6 comments
Downstream Downstream packaging issues etc. Feature Request Packaging Windows Related to Windows operating system
Comments
AmirsamanAhmadi commented Sep 5, 2023
Feature description
I hope this message finds you well. I am writing to request an upgrade of the default Python version used in QGIS from 3.9 to the latest stable version, which is 3.11.4 at the time of writing.
I understand that QGIS is a complex and multifaceted open-source GIS platform, and I genuinely appreciate all the hard work that the team puts into maintaining and improving it. Python plays a critical role in extending the functionality of QGIS through plugins and scripting, and using the latest Python version can provide numerous benefits, including performance improvements and access to new features and libraries.
I attempted to build QGIS against Python 3.11 myself, but unfortunately, I encountered difficulties and could not successfully complete the process. I believe that many other users may face similar challenges, especially those who rely on QGIS as a fundamental tool in their work. As such, having the latest Python version bundled with QGIS would streamline the installation process and ensure that users have access to the most up-to-date Python environment without the need for manual configuration.
I am aware that some users choose to use QGIS with Anaconda, which allows for greater flexibility in managing Python environments. However, in our organization, we have internal policies and licensing constraints that prevent us from using QGIS with Anaconda. Therefore, having the default QGIS distribution support Python 3.11 would be immensely valuable to us and many other users who share similar restrictions.
I understand that software development and integration decisions are complex and require careful consideration. Still, I kindly request that you evaluate the feasibility of upgrading the default Python version in QGIS to 3.11 in a future release. Your efforts in this regard would be greatly appreciated by the QGIS user community.
Thank you for your time and dedication to the QGIS project. I look forward to any updates or information you can provide regarding this request.
Additional context
The text was updated successfully, but these errors were encountered:
Разработка¶
— это бесплатное и открытое программное обеспечение, лицензированное Универсальной общественной лицензией GNU, версия 2.0 или более поздней.
Инструмент состоит из ряда компонентов. Первый — это плагин QGIS, поддерживающий расчет индикаторов, доступ к сырым данным, отчетности и производству печатных карт. Код для плагина и дальнейшие инструкции по его установке, если вы хотите модифицировать код, находятся в репозитории GitHub trends.earth.
Плагин QGIS поддерживается рядом разных скриптов Python, которые позволяют рассчитывать множество индикаторов на Google Earth Engine (GEE). Эти скрипты находятся в субпапке «gee» этого репозитория GitHub. Скрипты GEE поддерживаются модулем Python деградация земель , который включает код для обработки вводов и выводов для плагина, а также другие распространенные функции, поддерживающие расчет интегралов NDVI, статистическую значимость и другой общий код. Код для этого модуля доступен в репозитории деградация земель _ на GitHub.
Внизу приводятся дальнейшие подробности касательно того, как сделать вклад в Trends.Earth, работая над кодом плагина, модифицируя код обработки или содействуя переводом веб-сайта и плагина.
Модификация кода плагина QGIS¶
Скачивание кода trends.earth¶
Код Trends.Earth как для плагина, так и для скриптов Google Eearth Engine, которые его поддерживают, расположены на GitHub в репозитории «trends.earth »_. Клонируйте этот репозиторий в удобное место на вашем компьютере, чтобы убедиться, что вы располагаете самой последней версией кода.
Есть ряд разных веток репозитория trends.earth, которые находятся в активной разработке. Плагин официально поддерживает QGIS3, и большая часть разработки происходит на ветке «разработка». Ветка «qgis2» — это более старая версия плагина, и она поддерживает версию QGIS2 2.18+.
Установка зависимостей¶
Python¶
Плагин кодирован в Python. Вдобавок к тому, что он используется для запуска плагина через QGIS, Python также используют для поддержки управления плагином (смена версии, установка разрабатываемых версий и т.д.). Хотя Python включен в QGIS, вам потребуется локальная версия Python, которую вы можете настроить с помощью программного обеспечения, необходимого для управления плагина. Самый простой способ управлять множеством версий Python — это через дистрибутив Anaconda. Для работы по разработке плагина требуется Python 3. Чтобы скачать Python 3.7 (рекомендуется) через Anaconda, ознакомьтесь с этой страницей _ .
Зависимости Python¶
Чтобы работать с кодом trends.earth, вам необходимо, чтобы на вашем компьютере был установлен Invoke, а также ряд других пакетов, которые используются для управления документацией, переводами и т.д. Все эти пакеты перечислены в файле требований «dev» для Trends.Earth, так что их можно установить, пройдя в командной строке в корневой каталог папке кода trends.earth и набрав:
pip install -r requirements-dev.txt
Если вы используете Anaconda, вы сначала захотите установить виртуальную среду Python 3.7, прежде чем запустить указанную выше команду (и любые из других invoke-команд, перечисленных на странице). Один из способов сделать это — запустить «командную строку Anaconda», следуя инструкциям на этой странице Anaconda.
PyQt¶
PyQt5 — это набор графических инструментов, используемых QGIS3. Чтобы собрать пользовательский интерфейс для Trends.Earth для QGIS3, вам необходимо установить PyQt5. Пакет можно установить из pip, используя:
pip install PyQt5
PyQt4 — это набор графических инструментов, используемых QGIS2. Лучший ресурс для этого пакета на Windows — из набора пакетов, поддерживаемых Кристофером Гольке на UC Irvine. Чтобы скачать PyQt4, выберите подходящий пакет с этой страницы. Выберите подходящий файл для той версии Python, которую вы используете. Например, если вы используете Python 2.7, выберите версию «cp27» в названии файла. Если вы используете Python 3.7, выберите версию с «cp37» в названии файла. Выберите «amd64» для python 64-bit и «win32» для python 32-bit.
После скачивания по приведенной выше ссылке используйте «pip», чтобы установить его. Например, для колеса 64-bit для Python 3.7 вы запустите:
pip install PyQt4-4.11.4-cp37-cp37m-win_amd64.whl
Изменение версии плагина¶
Согласно договоренности, в Trend.Earth номера версий, которые заканчиваются нечетным числом (например, 0.65), это разрабатываемые версии, тогда как версии, которые заканчиваются четным числом (например, 0.66), это выпускные версии. Разрабатываемые версии плагина никогда не выпускаются через репозиторий QGIS, поэтому обычные пользователи плагина их никогда не видят. Разрабатываемые версии, заканчивающиеся на нечетное число, используются командой разработчиков Trend.Earth во время испытаний новых функций до их публичного выпуска.
Если вы желаете внести изменения в код и скачали публичный выпуск плагина (тот, который заканчивается четным числом), первый шаг — это обновить версию плагина до следующего за ним последовательного нечетного числа. Так, например, если вы скачали версию 0.66 плагина, вам понадобится обновить версию до 0.67, прежде чем вы начнете вносить свои изменения. В коде есть несколько мест, где упоминается версия (также, как и внутри каждого скрипта GEE), поэтому есть invoke-задача, которая помогает с изменением версии. Чтобы изменить эту версию до 0.67, вы запустите:
invoke set-version -v 0.67
Запуск приведенной выше команды обновит номер версии в каждом месте, где он упоминается в этом коде. Чтобы избежать путаницы, никогда не меняйте версию на ту, что уже была выпущена, а всегда УВЕЛИЧИВАЙТЕ значение метки версии на следующее нечетное число.
Испытание изменений в плагине¶
После внесения изменений в код плагина вам потребуется протестировать их, чтобы убедиться в том, что плагин ведет себя согласно ожиданий и что не возникнет никаких багов или ошибок. Плагин должен пройти исчерпывающие испытания, прежде чем будет выпущен в репозиторий QGIS (где его могут оценивать другие пользователи), чтобы убедиться, что никакие изменения кода не ломают плагин.
Чтобы протестировать любые изменения, которые вы внесли в плагин внутри QGIS, вам понадобится установить его локально. Есть invoke-задачи, которые помогают с этим процессом. Первый шаг, предшествующий установке плагина, это убедиться, что вы оснастили плагин всеми зависимостями, которые ему нужны для запуска из QGIS. Чтобы это сделать, запустите:
invoke plugin-setup
Приведенная выше задача должна быть выполнена сразу же после скачивания кода trends.earth, или если в зависимости для плагина были внесены какие-либо изменения. По умолчанию «плагин-настройка» будет использовать любые кешированные файлы на вашем компьютере. Чтобы начать с нуля, добавьте флажок «-с» (чисто) к приведенной выше команде.
После запуска «плагина-установки» вы готовы к установке плагина в папку плагинов QGIS на вашем компьютере. Чтобы сделать это, запустите:
invoke plugin-install
После запуска приведенной выше команды вам понадобится либо: 1) перезапустить QGIS, или 2) использовать Перезагрузчик плагина чтобы перезагрузить плагин Trends.Earth и посмотреть последствия внесенных вами изменений.
По умолчанию «плагин-установка» запишется сверху любых существующих файлов на вашем компьютере, но не тронет никаких данных (административные границы и т.д.), которые этот плагин мог скачать. Чтобы начать все сначала, добавьте флажок «-c» (чисто) к приведенной выше команде. Возможно, вам понадобиться закрыть QGIS, чтобы успешно выполнить чистую установку плагина, используя флажок «-с».
По умолчанию плагин-установка предполагает, что вы хотите установить плагин для использования в QGIS3. Чтобы установить плагин для использования в QGIS3, добавьте флажок «-v 2» в команду «плагин-установка». Помните, что плагин может быть, а может и не быть полностью функциональным на QGIS3 — этот плагин был изначально разработан для QGIS2 и все еще тестируется на QGIS3.
Синхронизация и внедрение изменений в двоичные файлы¶
Чтобы ускорить вычисления в Trends.Earth, некоторые из инструментов позволяют использовать предварительно скомпилированные двоичные файлы, которые были скомпилированы с использованием numba. Numba — это открытый компилятор, который может компилитровать код Python и NumPy, делая это быстрее, чем когда он запущен как обычный Python. Чтобы пользователям Trends.Earth не потребовалось скачивать Numba и все из его зависимостей, команда Trends.Earth делает предварительно скомпилированные двоичные файлы доступными для скачивания, если пользователи выбирают их установить.
Чтобы сгенерировать предварительно скомпилированные двоичные файлы для OS битностью 32/64 бита и версии Python, которая используется на вашем компьютере, используйте:
invoke binaries-compile
Для того чтобы приведенная выше команда работала, вам потребуется компилятор C++. Для Windows зайдите на эту страницу github, чтобы узнать, как установить компилятор Microsoft Visual C++, необходимый для версии Python. На MacOs вам, скорее всего, понадобится установить Xcode. На Linux установите подходящую версию GCC.
Чтобы сделать эти двоичные файлы публично доступными, их распространяют через бакет S3 сервисов Amazon Web. Чтобы загрузить в бакет эти двоичные файлы, сгенерированные приведенной выше командой, запустите:
invoke binaries-sync
Приведенная выше команда не сработает, если у вас нет ключей, дающих право доступа в бакет «trends.earth» на S3.
Указанная выше команда синхронизирует каждый индивидуальный двоичный файл с S3. Однако пользователи инструментария скачивают двоичные файлы как один файл zip, привязанный к версии плагина, которые они используют. Для того чтобы сгенерировать этот файл zip, чтобы пользователи Trends.Earth могли его оценить, запустите:
invoke binaries-deploy
Приведенная выше команда не сработает, если у вас нет ключей, дающих право доступа в бакет «trends.earth» на S3.
Построение файла ZIP плагина¶
Есть несколько invoke-задач, которые помогают построить файл ZIP, для того чтобы внедрить плагин в репозиторий QGIS или поделиться разрабатываемой версией плагина с другими. Чтобы заархивировать плагин и все его зависимости в файл ZIP, который можно установить, придерживаясь „процедуры, описанной в файле readme `_, запустите:
invoke zipfile-build
Эта команда создаст папку под именем «построить» в корневом каталоге папки кода trends.earth, и в этой папке она создаст файл «LDMP.zip». Этим файлом можно делиться с другими, которые могут использовать его для ручной установки Trends.Earth. Это может быть полезно, если есть необходимость поделиться с кем-то самыми свежими функциями, прежде чем они станут доступными в публично выпущенной версии плагина.
Внедрение файла ZIP разрабатываемой версии¶
Страница GitHub Trends.Earth дает ссылку на файл ZIP, который дает доступ пользователям, которые могут не быть разработчиками, к разрабатываемой версии Trends.Earth. Чтобы создать файл ZIP и сделать его доступным на этой странице (файл ZIP хранится на S3), запустите:
invoke zipfile-deploy
Приведенная выше команда не сработает, если у вас нет ключей, дающих право доступа в бакет «trends.earth» на S3.
Модификация кода обработки Earth Engine¶
Все скрипты обработки Google Earth Engine (GEE), используемые Trends.Earth, сберегаются в папке «gee» под главной папкой trends.earth. Чтобы эти скрипты были доступны пользователям плагина trends.earth QGIS, они должны быть внедрены в сервис api.trends.earth, поддерживаемый Международным обществом сохранения природы, чтобы позволить пользователям плагина использовать Earth Engine без необходимости уметь программировать или иметь индивидуальные пользовательские учетные записи на GEE. Ниже описано, как протестировать и внедрить скрипты GEE, которые будут использоваться с Trends.Earth.
Настройка зависимостей¶
trends.earth-CLI¶
Пакет Python «trends.earth-CLI» требуется для работы с сервером api.trends.earth server. Этот пакет находится на GitHub в репозитории trends.earth-CLI.
Первый шаг — это клонировать репозиторий на ваш компьютер. Мы рекомендуем вам клонировать репозиторий в ту же папку, где находится ваш код trends.earth. Например, если у вас на компьютере была папка «Код», клонируйте и репозиторий trends.earth (код для плагина QGIS и связанные с ним скрипты GEE), и репозиторий trends.earth-CLI в одну и ту же папку.
После настройки вашей системы согласно рекомендациям выше, trends.earth-CLI будет работать с задачами вызова, использованными для управления trends.earth без модификаций. Однако, если вы загружаете trends.earth-CLI в другую папку, вам нужно добавить файл с названием «invoke.yaml» в корневой каталог хранилища trends.earth, и в этом файле сообщить Trends.Earth, где расположить код trends.earth-CLI. Этот файл YAML должен выглядеть примерно так, как показано ниже (если вы загрузили код в Windows в папку с названием «C:/Users/azvol/Code/trends.earth-CLI/tecli»):
gee: tecli: "C:/Users/azvol/Code/trends.earth-CLI/tecli"
Опять же, вам не нужно добавлять этот файл .yaml, если вы настроили систему по как рекомендациям выше.
докер¶
Локальное тестирование скрипта Earth Engine¶
После установки пакета trends.earth-CLI вам нужно настроить файл .tecli.yml с токеном доступа к учётной записи службы GEE для тестирования скриптов в GEE. Для настройки учётной записи службы GEE для tecli, сначала получите ключ для своей учётной записи службы в формате JSON (из google cloud console), потом закодируйте в base64. Введите этот закодированный в base64 ключ в tecli с помощью следующей команды:
invoke tecli-config set EE_SERVICE_ACCOUNT_JSON key
где «ключ» — ключ учётной записи службы, закодированный в base64, в формате JSON.
При преобразовании кода, определяющего скрипт для запуска в GEE из JavaScript в Python, может быть полезно провести локальное тестирование скрипта без развертывания его на сервере api.trends.earth. Чтобы это сделать, используйте задачу вызова run . Например, чтобы тестировать скрипт «land_cover», перейдите в корневой каталог кода Trends.Earth и в командной строке выполните:
invoke tecli-run land_cover
Будет использован пакет trends.earth-CLI для создания и выполнения докерного контейнера, который попытается выполнить скрипт «land_cover». Если в скрипте есть синтаксические ошибки, они будут видны при выполнении контейнера. Перед вводом нового скрипта в api.trends.earth убедитесь, что invoke tecli-run может выполнять скрипты без ошибок.
При использовании invoke tecli-run может возникать ошибка с текстом:
Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values and use a clock with skew to account for clock differences between systems.
Эта ошибка может возникать, если часы на докером контейнере не синхронизированы с часами системы. Перезапуск докера должен исправить эту ошибку.
Развёртывание скрипта GEE на api.trends.earth¶
После окончания тестирования скрипта GEE, если вы хотите, чтобы он был доступен через плагин QGIS (и другим пользователям Trends.Earth), можно развернуть его на сервере api.trends.earth. Первый шаг в процессе — вход на сервер api.trends.earth. Для входа выполните:
invoke tecli-login
Вы должны ввести имя пользователя и пароль. Это те же имя пользователя и пароль, которые вы используете для входа на сервер Trends.Earth из плагина QGIS. Если вы не являетесь администратором, вы сможете войти, но следующая команда не будет работать. Для загрузки скрипта, например, скрипта «land_cover», на сервер, выполните:
invoke tecli-publish -s land_cover
Если этот скрипт уже существует на сервере, вы должны будете выбрать, хотите ли вы переписать существующий скрипт. Будьте очень внимательны при загрузке скриптов с чётно пронумерованными версиями, так как это скрипты, находящиеся в открытом доступе, и любая ошибка будет влиять на всех, использующих плагин. Во время тестирования всегда пользуйтесь версиями с номерами разработки (нечетные номера).
После публикации скрипта на сервере вы можете использовать задачу tecli-info для проверки статуса скрипта, чтобы узнать, успешно ли он развернут — хотя сообщение о построении скрипта может занять несколько минут). Для проверки статуса разворачиваемого скрипта выполните:
invoke tecli-publish -s land_cover
Если вы делаете новый релиз плагина и хотите загрузить ВСЕ скрипты GEE одновременно (это необходимо при изменении номера версии плагина), выполните:
invoke tecli-publish
Опять же, никогда не выполняйте это в версиях, находящихся в открытом доступе, если только вы не хотите переписать все находящиеся в открытом доступе скрипты, используемые плагином.
Редактирование шаблонов векторных слоёв¶
Trends.Earth позволяет пользователям оцифровывать новые векторные признаки для определения областей особых интересов.
На сегодняшний день поддерживаются только слои «ложного срабатывания/несрабатывания», но при необходимости можно добавить больше. Любой векторный слой создаётся из макета файлов GeoPackage, который можно найти внутри папки data/error_recode каталога установки плагинов. Для каждого типа вектора есть 6 макетных файлов, по одному на каждый официальный язык UN. Языковой код ISO добавляется в качестве суффикса к названию файла. Это необходимо для создания локализованных меток в формах атрибута. Когда запрашивается создание векторного слоя, QGIS осуществляет поиск макетного файла, принимая во внимание региональные настройки QGIS, как запасной вариант используется версия макетного файла на английском языке.
Для изменения схемы слоя необходимо изменить соответствующие макетные файлы в папке data/error_recode каталога установки плагинов. Также макетный файл содержит встроенную стилистическую правку по умолчанию и конфигурацию формы атрибута, автоматически применяемую к слою при загрузке в QGIS.
Для отображения диаграмм в форме атрибута используется встроенный виджет QML. Данные диаграммы хранятся в диаграмме атрибутов векторного слоя. Величины из соответствующих полей извлекаются с помощью выражения.
Код для генерирования диаграмм выглядит как:
import QtQuick 2.0 import QtCharts 2.0 ChartView width: 380 height:200 margins top: 0; bottom: 0; left: 0; right: 0> backgroundColor: "#eeeeec" legend.alignment: Qt.AlignBottom antialiasing: true ValueAxis id: valueAxisY min: 0 max: 100 > BarSeries id: mySeries axisY: valueAxisY axisX: BarCategoryAxis categories: ["Productivity", "Land cover", "Soil organic carbon"] > BarSet label: "Degraded"; color: "#9b2779"; values: [expression.evaluate("\"prod_deg\""), expression.evaluate("\"land_deg\""), expression.evaluate("\"soil_deg\"")] > BarSet label: "Improved"; color: "#006500"; values: [expression.evaluate("\"prod_imp\""), expression.evaluate("\"land_imp\""), expression.evaluate("\"soil_imp\"")] > BarSet label: "Stable"; color: "#ffffe0"; values: [expression.evaluate("\"prod_stab\""), expression.evaluate("\"land_stab\""), expression.evaluate("\"soil_stab\"")] > > >
Для извлечения значения поля используется функция«expression.evaluate(»»prod_deg»»)«, единственный аргумент, который она принимает при этом — имя поля. В диаграмме слоёв ложного срабатывания/несрабатывания есть три индикатора: продуктивность, земляной покров и почвенный органический углерод. Для каждого индикатора плагин сохраняет три величины: процент устойчивого, ухудшенного и улучшенного состояния полигональной области. Например, в случае, когда поля индикатора продуктивности будут:
- prod_deg — ухудшенная продуктивность
- prod_stab — устойчивая продуктивность
- prod_imp — улучшенная продуктивность
Такой же подход при присваивании имён применяется к земляному покрову ( land_* fields) и почвенному органическому углероду ( soil_* fields).
Вычисление процента площади производится с помощью функции пользовательского выражения, код можно найти в файле charts.py в корневом каталоге плагина. Функция оптимизирована для работы с большими полигонами и использует следующий рабочий процесс. Для заданной геометрии найдите bbox и извлеките подмножество растрового изображения, используя этот bbox. Выполните растеризацию геометрии в оперативной памяти и примените ее в качестве маски к растру. Затем подсчитайте количество пикселей, имеющих конкретное значение, и подсчитайте процент. Так как подсчет пикселей построен на функциях массива numpy, подсчет производится очень быстро даже для больших полигонов.
При первой попытке редактировать векторный слой пользователю представляется диалог, в котором нужно выбрать, какие наборы данных использовать для индикаторов. Затем плагин создаст величины выражения по умолчанию для всех полей индикатора, и величина будет обновляться при каждом изменении геометрии.
Работа с метаданными набора данных¶
Метаданные набора данных хранятся в формате QGIS QMD. Эти файлы QMD могут быть созданы для каждого растра индивидуально и также для целого набора данных. Диалог редактирования метаданных открывается из меню Edit metadata в Trends.Earth dock.
Когда набор данных экспортируется в ZIP, преобразование в ISO XML выполняется с использованием трансформации XSLT. Соответствующая трансформация расположена в поддиректории data\xsl в папке установки плагина.
Актуализация системы отчётности¶
Обзор системы отчётности¶
Система отчётности создана как расширяемая и интерактивная для пользователей через неблокирующие операции. Система в значительной степени использует классы QgsProject и QgsPrintLayout , которые не являются поточно-ориентированными, поэтому используются qgis_process для тяжёлой работы генерирования отчётов (и диаграмм). Больше информации о qgis_process здесь.
Есть два основных этапа действия набора инструментов при создании отчётов и диаграмм для слоёв задачи по умолчанию:
- Создаётся объект ReportTaskContext , включающий объект ReportConfiguration (см. Настройка параметров отчета ) и объект Job , представленный в панели Datasets. Этот объект ReportTaskContext сериализуется в файл формата JSON, а потом переносится как один из аргументов в объект ReportProcessHandlerTask (который наследует от QgsTask).
- Объект ReportProcessHandlerTask инициирует отдельные экземпляры qgis_process и передает маршрут файлу формата JSON как вклад в алгоритм процесса trendsearth:reporttask . Это тонкая обёртка, которая десериализирует файл в объект ReportTaskContext и передает его в объект ReportTaskProcessor , отвечающий за создание отчётов и проект QGIS. Для алгоритмов, требующих диаграмм, объект ReportTaskProcessor передает объект-задание объекту AlgorithmChartsManager , который проверяет наличие заданной конфигурации диаграммы для алгоритма задачи. Если она определена, создается соответствующая диаграмма в виде файлов PNG. (Смотрите более подробно о конфигурациях диаграмм Добавление конфигурации диаграммы )
На диаграмме ниже этот процесс проиллюстрирован подробно:

* Для увеличения масштаба, нажмите на изображение.
Некоторые из названий функций на диаграмме выше были упрощены для удобства иллюстрации. Упомянутые классы можно найти в модулях LDMP.reports и LDMP.processing_provider.report.
Добавление переменных макета отчёта¶
Переменные отчёта предоставляют контекстную информацию, связанную с задачей, слоем (или лентой) или Отчеты в процессе выполнения отчёта. В данный момент инструментарий поддерживает переменные, перечисленные в разделе Переменные выражения макета .
Каждая переменная определена как namedtuple в модуле LDMP.reports.expressions и, следовательно, обновляется и оценивается с помощью объекта ReportTaskProcessor .
Чтобы добавить новую задачу или переменные актуального слоя, следуйте инструкциям ниже.
Переменная задачи¶
Позволяет добавлять в макет отчёта информацию об актуальной задаче, которая выполняется. Информация о каждой переменной задачи инкапсулируется в объекте JobAttrVarInfo , который состоит из четырех атрибутов:
Величина по умолчанию
Присваивайте название объекту Job , как оно используется в точечном представлении. Например, id соответствует job.id . Вы даже можете использовать точечное представление, обращаясь к атрибутам во внутренних вложенных классах, например, results.uri.uri .
Название переменной макета отчёта. Должно содержать префикс te_job_ .
Величина по умолчанию, которую следует использовать для var_name , преимущественно применяется при разработке макетов.
Объект-функция, которая будет использована для преобразования величины атрибута задачи в формат, совместимый с выражениями QGIS. Например, str можно использовать для преобразования величины id задачи из UUID в строку. Также вы можете использовать здесь лямбда-функции.
Фрагмент кода ниже показывает, как добавить перемененную te_job_result_name , которая соответствует job.results.name .
# LDMP/reports/expressions.py def _job_attr_var_mapping() -> typing.List[JobAttrVarInfo]: return [ . JobAttrVarInfo('results.name', 'te_job_result_name', '', str), . ]
Переменная слоя¶
Предоставляет информацию об актуальном выполняемом слое растра. Информация этой переменной инкапсулирована в объекте LayerVarInfo , включающем три атрибута:
Величина по умолчанию
Название переменной макета отчёта. Должно содержать префикс te_current_layer_ .
Величина по умолчанию, которую следует использовать для var_name , преимущественно применяется при разработке макетов.
Объект-функция, которая будет использована для извлечения и/или преобразования величины из QgsRasterLayer object в формат, совместимый с выражениями QGIS. Здесь вы тоже можете использовать лямба-функции.
Например, lambda layer: layer.name() возвращает имя слоя.
Фрагмент кода ниже показывает, как добавить перемененную te_current_layer_height , которая соответствует высоте слоя растра.
# LDMP/reports/expressions.py def _current_job_layer_var_mapping() -> typing.List[LayerVarInfo]: return [ . LayerVarInfo( 'te_current_layer_height', '', lambda layer: layer.height() ) . ]
Эти переменные доступны только в области макета.
Добавление конфигурации диаграммы¶
Диаграммы могут быть сгруппированы с использованием объекта конфигурации диаграммы, соответствующего определённому алгоритму. Определение конфигурации новой диаграммы — трёхступенчатый процесс:
-
Создать новый класс диаграмм, наследующий из BaseChart в модуле LDMP.reports.charts . Применение функции export для определения типа и свойств диаграмм, с использованием библиотеки Python Plotly , которая поставляется в составе QGIS. Наконец, в функции export назовите функцию save_image для записи Figure объекта Plotly в качестве файла изображения, используя любой из форматов, поддерживаемых классом Qt QImageWriter . Вы можете также указать маршрут по отношению к выходному каталогу корня, который также доступен в качестве атрибута в основном классе. Смотрите фрагмент кода ниже:
# LDMP/reports/charts.py Class MyCustomChart(BaseChart): def export(self) -> typing.Tuple[bool, list]: status = True messages = [] # Create chart Figure using Plotly and set properties fig = go.Figure(. ) # Add warning or error messages messages.append('Colour list not supported.') # Set image path in dataset's reports folder img_path = f'self.root_output_dir>/chart-NDVI.png' # Save image and append its path self.save_image(fig, img_path) self._paths.append(img_path) return status, messages
# LDMP/reports/charts.py Class AlgorithmChartsManager: def _set_default_chart_config_types(self): . self.add_alg_chart_config('land-cover', LandCoverChartsConfiguration) self.add_alg_chart_config('productivity', MyCustomLandProductivityChartsConfiguration) .
Участие в создании документации¶
Обзор¶
Документация Trends.Earth производится с использованием Sphinx, записывается в формате reStructuredText. Если вы незнакомы с каким-то из этих инструментов, ознакомьтесь с их документацией, чтобы узнать об их использовании.
Документация Trends.Earth хранится в папке «docs» folder в основном каталоге trends.earth. Внутри этой папки есть несколько ключевых файлов и папок, требующих внимания:
- build: содержит документацию build для trends.earth (в формате PDF и HTML). Она появится на вашем устройстве только после выполнения задачи вызова docs-build .
- i18n: содержит переводы документации на другие языки. Эти файлы обычно обрабатываются автоматически с использованием задач вызова, поэтому у вас не должно быть причин для изменений содержания этой папки.
- resources: содержит любые ресурсы (в основном изображения и PDF), относящиеся к документации. В настоящий момент есть только одна папка («EN» для английского), так как все изображения в документации взяты из английской версии плагина — при необходимости дополнительные папки могут быть добавлены в «ресурсы» с двухбуквенными кодами языка, чтобы включить изображения, связанные с определенным языком.
- source: содержит файлы исходного кода reStructuredText, определяющие документацию (актуальный текст на английском языке и файлы, которые с большой вероятностью требуют изменения).
Установка зависимостей¶
Зависимости Python¶
Для работы с этой документацией следует вызвать Sphinx, sphinx-intl и sphinx-rtd-theme (тема вебсайта Trends.Earth), установленные на вашем устройстве. Эти пакеты перечислены в файле требований «dev» для Trends.Earth, то есть, они могут быть установлены путем выполнения навигации в командной строке к корню папки trends.earth code при вводе:
pip install -r requirements-dev.txt
LaTeX¶
LaTeX используется для производства вывода документации Trends.Earth в формате PDF.
Чтобы установить в Windows, следуйте этим инструкциям для установки LaTeX из дистрибутива proTeXt из файла `zip, доступного здесь`_ . Установщик LaTeX довольно большой (несколько Гб), поэтому загрузка и установка может потребовать времени.
Для MacOS, MacTeX — хороший вариант, может быть установлен при выполнении этих инструкций.
В Linux установка LaTeX должна быть гораздо проще — используйте менеджер пакета дистрибутива для выяснения и установки включенного по умолчанию дистрибутива LaTeX.
Qt Linguist¶
Qt Linguist также требуется для формирования строк на основе кода и GUI для перевода. Команда «lrelease» должна быть доступна и включена в ваш маршрут. Попробуйте:
lreleaseв окне терминала. Если файл не обнаружен, необходимо установить Qt Linguist. Эта страница один источник установщиков для Qt Linguist. После установки Qt Linguist необходимо добавить папку, содержащую команду lrelease в маршрут, так чтобы скрипт вызова Trends.Earth мог её найти.
Актуализация и формирование документации¶
После установки требований sphinx вы готовы начать модификацию документации. Требующие модификации файлы находятся в папке «docs\source». После внесения изменения в эти файлы вам понадобится сформировать документацию, чтобы увидеть результаты. Есть две версии документации Trends.Earth: HTML-версия (используется для сайта) и PDF-версия (для загрузки на устройство). Для формирования документации Trends.Earth используйте задачу вызова «docs-build». По умолчанию эта задача сформирует полную документацию для Trends.Earth, в HTML и PDF, для всех поддерживаемых языков. Это может занять некоторое время (до нескольких часов). Если вы только тестируете результаты некоторых малых изменений в документации, лучше всего использовать опцию -f (для «fast/быстро»). Это действие сформирует только документацию в формате HTML на английском языке и займёт всего несколько секунд. Для формирования в быстром режиме воспользуйтесь:
invoke docs-build -f
Выполнение команды выше займёт несколько секунд, если вы посмотрите по адресу «docs\build\html\en», вы увидите HTML-версию документации. Загрузите файл «index.html» в веб-браузере, чтобы увидеть, как он выглядит.
Для формирования полной документации для всех языков в форматах PDF и HTML (помните, что выполнение этого может занять несколько часов), выполните:
invoke docs-build
После выполнения вышеупомянутой команды вы увидите документацию на английском языке в формате HTML по адресу «docs\build\html\en», а в формате PDF по адресу «docs\build\html\en\pdfs».
Если вы хотите протестировать конкретный язык (при тестировании перевода, например), вы можете указать две буквы кода языка для того, чтобы сформировать документы только для этого языка. Например, для формирования документации только на испанском, выполните:
invoke docs-build -l es
Опции можно комбинировать, то есть, можно использовать быстрый вариант для формирования HTML-версии документации на испанском языке, выполняя:
invoke docs-build -f -l es
Формируя полную документацию для сайта, полезно первоначально удалить старые версии документации, так как они могут содержать файлы, более не актуальные для обновленной документации. Чтобы это сделать, используйте опцию -c (clean/очистить):
invoke docs-build -c
В общем, команда docs-build ДОЛЖНА быть выполнена без ошибок, если вы планируете поделиться документацией или разместить её на сайте. Однако при локальном тестировании вам может быть удобно проигнорировать ошибки документации, которые появляются только для некоторых языков (например, из-за синтаксических ошибок, связанных с ошибками перевода), и продолжить формирование оставшейся документации, несмотря на наличие и отсутствие ошибок. Чтобы это сделать, воспользуйтесь опцией -i (ignore errors / игнорировать ошибки):
invoke docs-build -i
При внесении изменений в текст документации будет полезно направить последние строки в Transifex, чтобы они могли быть переведены. Для обновления строк в Transifex с изменениями, выполните:
invoke translate-push
Чтобы успешно выполнить упомянутую выше команду, нужно иметь ключ к учетной записи Trends.Earth Transifex.
Формирование окончательной документации¶
Перед созданием новой документации всегда используйте последние версии перевода из Transifex, чтобы все переводы были актуальными. Для этого выполните:
invoke translate-pull
Для формирования версии документации для общего просмотра (на сайте или в формате PDF), нужно сгенерировать всю документацию, используя команду docs-build без дополнительных параметров:
invoke docs-build
Этот процесс должен быть выполнен успешно без ошибок. Если в процессе возникают ошибки, рассмотрите сообщения об ошибках и внесите необходимые изменения, чтобы сформировать версию успешно. После окончания формирования без ошибок все файлы готовы для размещения на сайте.
Обе из команд выше имеют также опции -f (force/сила), которые принудительно выводят или вводят последние переводы из или в Transifex (соответственно). Используйте эти опции только если вы АБСОЛЮТНО уверены в том, что вы делаете, так как они могут полностью переписать переводы в Transifex, что приведет к утрате работы, сделанной переводчиками, если последние переводы еще не были утверждены в github.
Добавление нового текста документации¶
Любые новые файлы .rst, добавленные в документацию, должны быть добавлены к файлам нескольких конфигураций, для того, чтобы они появились в меню навигации, были нужным образом переведены и, в случае учебников, чтобы они формировались в формате PDF-файлов, которые можно загрузить на устройство.
- docs\source\index.rst: добавляйте файлы .rst в нужное место здесь, чтобы они были связаны с меню навигации.
- .tx\config: вносите новые файлы .rst здесь (в таком же формате, как и уже включенные файлы), чтобы уведомить программу перевода об их наличии и необходимости обработки
- docs\source\conf.py: если вы хотите сгенерировать PDF-файл страницы сайта, вы должны внести эту страницу в список latex_documents . Обычно мы делаем это только для страниц учебников, которые мы хотим сделать доступными участникам семинара в виде отдельных PDF-файлов. Каждая страница на этом сайте будет включена в PDF-версию на сайте в целом, независимо от того, включена ли она в список latex_documents .
Добавление новых изображений или других ресурсов¶
Любые новые изображения или другие ресурсы (PDF и другие), которые необходимы документации, должны быть добавлены по адресу «docs\resources\en». При желании можно загрузить разные версии изображения, чтобы изображение появилось с необходимым переводом. Это может быть полезно, если вы хотите, чтобы интерфейс GUI отображался на нужном языке, например. Для этого сначала загрузите копию изображения к «docs\resourcesen» (с текстом на английском языке). После создайте копию изображения с переведенным текстом и разместите это изображение в папку нужного языка (например, изображение, показывающее перевод на испанский, должно находиться по адресу «docs\resources\es»). Английская версия изображения будет использована по умолчанию для всех языков, для которых нет изображения с переводом, тогда как при наличии локализованной версии, будет использована она.
Есть другая папка, docs\\source\\static , используемая для временного удержания ресурсов во время выполнения скриптов, формирующих документацию Trends.Earth. Вы можете внести изображения в эту папку, если вы когда-либо формировали документацию на этом устройстве. Эта папка не должна использоваться для добавления новых ресурсов — новые ресурсы всегда добавляются здесь docs\\resources\\en , а переведенные изображения добавляются в папку соответствующего языка здесь docs\\resources .
Участие в качестве переводчика¶
Переводы для плагина QGIS и этого сайта управляются transifex. Если вы хотите принять участие в переводе плагина и документации (мы будем рады вашей помощи!), вы можете отправить запрос на присоединение к нашей команде через transifex, или написав нам по адресу trends . earth @ conservation . org.
© Copyright 2017-2023, Conservation International. Ревизия fb274e09 .