-1

我正在编写一个脚本,让我连接到 Sentinel 卫星数据库以下载请求的地图文件。

from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt

def get_available(input_geojson, user, password, date_start, date_end, satellite, sensormode, product_type):

    # LogIn
    api = SentinelAPI(user, password , 'https://scihub.copernicus.eu/dhus')

    # Input parameter of the search
    footprint = geojson_to_wkt(read_geojson(input_geojson))   # irrelevant to the question
    products = api.query(footprint,
                         date = (date_start, date_end),
                         platformname = satellite,
                         sensoroperationalmode = sensormode,
                         producttype = product_type,
                         )

我的问题取决于我将使用哪种“卫星”输入将改变其他哪些参数是必要的、必需的甚至是允许的。有些不需要“sensormode”,有些可能需要“cloudcoverage”。我将如何在函数内的函数中编写带有变量/可选参数的干净代码?我必须列出所有可能的论点吗?

4

3 回答 3

1

我发现 Crawl Cycle 的答案非常 Pythonic 和美丽,所以我建议这样做。无论如何,我在这方面工作很开心,所以这是我对你正在寻找的东西的解释:)

import inspect


def foo_api(*, foo=None):
    print(f'foo_api: foo={foo}')

def bar_api(*, bar=None):
    print(f'bar_api: bar={bar}')

_API_BY_PARAMETERS = {
    frozenset(inspect.signature(api).parameters): api
    for api in (foo_api, bar_api)
}


def api(**kwargs):
    """Selects the correct API to call based on the given kwargs."""
    actual_params = frozenset(kwargs)
    if actual_params in _API_BY_PARAMETERS:
        actual_api = _API_BY_PARAMETERS[actual_params]
        return actual_api(**kwargs)
    else:
        param_errors = (
            (api.__name__,
             ', '.join(sorted(expected_params - actual_params)),
             ', '.join(sorted(actual_params - expected_params)))
            for expected_params, api in _API_BY_PARAMETERS.items())
        raise TypeError(
            'Arguments must match exactly with one of the APIs, but found '
            'the following differences: ' +
            '; '.join(
                f'{api_name} -> missing=[{missing}], unexpected=[{unexpected}]'
                for api_name, missing, unexpected in param_errors))

在线试用

有一些约束可以使这个实现尽可能简洁:

  • 所有 API 签名都必须是唯一的。
  • 所有 API 签名都只接受关键字参数。
于 2020-11-04T00:56:16.323 回答
1

那个 api 使用起来似乎太乏味了。更好地将参数与类分组。

from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt


class Satellite:
    def __init__(self, name, producttype, sensormode=None, cloudcoverage=None):
        self.name = name
        self.producttype = producttype
        self.sensormode = sensormode
        self.cloudcoverage = cloudcoverage


class SentinelConnection:
    def __init__(self, input_geojson, user, password):
        self.input_geojson = input_geojson
        self.user = user
        self.password = password
        self.api = None
        self.footprint = None

    def __enter__(self):
        self.api = SentinelAPI(self.user, self.password,
                               'https://scihub.copernicus.eu/dhus')
        self.footprint = geojson_to_wkt(read_geojson(self.input_geojson))

    def __exit__(self, exc_type, exc_val, exc_tb):
        # logout here
        pass


def get_available(conn, satellite, date_start, date_end):
    s = satellite
    products = conn.api.query(conn.footprint,
                              date=(date_start, date_end),
                              platformname=satellite,
                              sensoroperationalmode=s.sensormode,
                              producttype=s.product_type,
                              )


def main():
    with SentinelConnection("abc.json", "name", "password") as conn:
        satellite = Satellite('Sputnik X', 'military satellite')
        get_available(conn, satellite, date_start, date_end)

我对什么是足迹一无所知。如果不同的查询可以使用不同的足迹并且查询经常重用相同的足迹,则为足迹创建一个 Location 类。

于 2020-11-04T00:26:58.580 回答
0

我相信 **kwargs 会很好地解决这个问题。这允许您将任何 keywork 参数传递给函数,而无需在函数签名中指定 then ,即:

def foobar(foo, **kwargs):
   bar = kwargs["bar"]
   return foo + bar


barfoo = foobar(foo='something', bar='other_thing')
于 2020-11-03T23:45:33.163 回答