Клиент против Сервера

Клиентские библиотеки Earth Engine для Python и JavaScript преобразуют сложный геопространственный анализ в запросы Earth Engine. Код, который вы пишете для клиентской библиотеки, может содержать смесь ссылок на объекты на стороне клиента и переменные, представляющие объекты на стороне сервера.

Важно отличать объекты Earth Engine от других объектов или примитивов Python или JavaScript, которые могут быть в вашем коде. Вы можете манипулировать объектами на сервере, манипулируя объектами «прокси» на стороне клиента в вашем сценарии. Вы можете распознать прокси-объект как что угодно, начинающееся с ee . Эти прокси-объекты Earth Engine не содержат никаких фактических данных и представляют собой просто дескрипторы объектов на сервере. Для начала рассмотрим строковый объект на стороне клиента (который НЕ является прокси-объектом):

Редактор кода (JavaScript)

var clientString = 'I am a String';
print(typeof clientString);  // string

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

client_string = 'I am a String'
print(type(client_string))  # str

Из выходных данных обратите внимание, что клиент (веб-браузер или блокнот) интерпретировал этот код и запустил его, определив, что переменная имеет тип string . Теперь предположим, что вы хотите, чтобы Earth Engine мог что-то делать с этой строкой. Для этого вам нужно поместить строку в красивый контейнер и отправить ее в Google. Этот контейнер является прокси-объектом. Вот пример:

Редактор кода (JavaScript)

var serverString = ee.String('I am not a String!');
print(typeof serverString);  // object
print('Is this an EE object?',
    serverString instanceof ee.ComputedObject);  // true

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

server_string = ee.String('I am not a String!')
print(type(server_string))  # ee.ee_string.String
print(
    'Is this an EE object?', isinstance(server_string, ee.ee_string.String)
)  # True

Обратите внимание на вывод, что ee.String является object , а НЕ string . Точнее, это ee.computedObject , что означает, что это прокси-объект для чего-то на сервере. Думайте о ee.Thing как о способе поместить вещь в контейнер для отправки в Google. Ваш клиент не знает, что находится в контейнере, но вы можете узнать, что в нем, распечатав это:

Редактор кода (JavaScript)

print(serverString);  // I am not a String

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

print(server_string.getInfo())  # I am not a String

Чтобы увидеть, как выглядит сам контейнер, напечатайте строковое представление объекта:

Редактор кода (JavaScript)

print(serverString.toString());  // ee.String("I am not a String!")

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

print(server_string)  # ee.String({"constantValue": "I am not a String!"})

Если по какой-то причине вам нужно использовать Python или JavaScript, работающий в клиенте, для управления всем, что находится в контейнере, используйте getInfo() чтобы получить содержимое контейнера и присвоить его переменной:

Редактор кода (JavaScript)

var someString = serverString.getInfo();
var strings = someString + '  Am I?';
print(strings);  // I am not a String!  Am I?

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

some_string = server_string.getInfo()
strings = some_string + '  Am I?'
print(strings)  # I am not a String!  Am I?

Зацикливание

Поскольку клиент не знает, что находится в объектах ee.Thing на стороне сервера, операции на стороне клиента, такие как условные выражения и циклы for, с ними не работают. По этой причине и во избежание синхронных вызовов getInfo() используйте серверные функции, насколько это возможно. Например, рассмотрим следующие два способа создания списка:

Не рекомендуется — цикл for на стороне клиента

Редактор кода (JavaScript)

var clientList = [];
for(var i = 0; i < 8; i++) {
  clientList.push(i + 1);
}
print(clientList);

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

client_list = []
for i in range(8):
  client_list.append(i + 1)
print(client_list)

Рекомендуется — сопоставление на стороне сервера.

Редактор кода (JavaScript)

var serverList = ee.List.sequence(0, 7);
serverList = serverList.map(function(n) {
  return ee.Number(n).add(1);
});
print(serverList);

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

server_list = ee.List.sequence(0, 7)
server_list = server_list.map(lambda n: ee.Number(n).add(1))
print(server_list.getInfo())

Пример сопоставления на стороне сервера немного глуп, потому что тот же список можно создать просто с помощью ee.List.sequence(1, 8) , но он иллюстрирует некоторые важные концепции. Первая концепция — это map() , которая просто применяет одну и ту же функцию ко всему в списке. Поскольку эта функция выполняется на сервере, клиентские функции, такие как getInfo() и print() не будут работать в сопоставленной функции. По этой причине код i + 1 необходимо заменить эквивалентным кодом на стороне сервера: ee.Number(n).add(1) . Важно отметить, что n — это объект, который существует только на сервере. Поскольку функция не знает тип своего аргумента, его необходимо привести к ee.Number .

(Описание функций, выполняемых на клиенте, см. в разделе «Функции клиента и сервера» .)

Также стоит отметить, что иногда функциональность на стороне клиента оказывается удобной. Например, предыдущий цикл for можно использовать для создания списка и обертывания его серверным объектом:

Редактор кода (JavaScript)

var toServerList = ee.List(clientList);

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

to_server_list = ee.List(client_list)

Помните, что обработка на стороне клиента выполняется в вашем ноутбуке или браузере, в процессоре хост-компьютера, поэтому она может быть менее эффективной, чем использование Earth Engine для выполнения работы на сервере. Кроме того, чтобы избежать потенциально неожиданных результатов, рекомендуется избегать смешивания функций клиента и сервера в ваших сценариях. В разделе «Условия» приведен пример возможных непредвиденных последствий.

Условные предложения

Объекты на стороне сервера не обязательно работают с функциями на стороне клиента, и наоборот. Например, рассмотрим случай логической переменной на стороне сервера:

Редактор кода (JavaScript)

var myList = ee.List([1, 2, 3]);
var serverBoolean = myList.contains(5);
print(serverBoolean);  // false

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

my_list = ee.List([1, 2, 3])
server_boolean = my_list.contains(5)
print(server_boolean.getInfo())  # False

Как показано в следующем примере, переменная не ведет себя в условном выражении на стороне клиента, поскольку это объект на стороне сервера. Чтобы правильно проверить логическое значение на стороне сервера, используйте функцию на стороне сервера:

Не рекомендуется — условно на стороне клиента

Редактор кода (JavaScript)

var clientConditional;
if (serverBoolean) {
  clientConditional = true;
} else {
  clientConditional = false;
}
print('Should be false:', clientConditional);  // True!

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

if server_boolean:
  client_conditional = True
else:
  client_conditional = False
print('Should be False:', client_conditional)  # True!

Рекомендуется — условно на стороне сервера

Редактор кода (JavaScript)

var serverConditional = ee.Algorithms.If(serverBoolean, 'True!', 'False!');
print('Should be false:', serverConditional);  // False!

Настройка Python

См. страницу «Среда Python» для получения информации об API Python и использовании geemap для интерактивной разработки.

import ee
import geemap.core as geemap

Колаб (Питон)

server_conditional = ee.Algorithms.If(server_boolean, 'True!', 'False!')
print('Should be False:', server_conditional.getInfo())  # False!

Функции клиента и сервера

В предыдущих разделах описано несколько причин, по которым неэффективно или нелогично смешивать клиентские и серверные объекты и функции. Какие объекты и функции являются клиентскими, а какие — серверными? В общем, все, что инициализируется как ee.Thing является серверным объектом, а любой метод этого объекта, ee.Thing.method() , является серверной функцией. Объекты и функции, которые появляются в справочнике по Python или JavaScript, являются клиентскими. Как отмечалось ранее, вы можете использовать функции на стороне клиента для создания объекта, а затем обернуть его, передав объект на стороне клиента конструктору Earth Engine, например ee.String() .