GrpcIndex

GrpcIndex runs the data-plane methods of Index over gRPC, and adds *_async() methods that return a PineconeFuture. It has no documents namespace: use Index or AsyncIndex for a schema-based index. Get one from pinecone.Pinecone.index() with grpc=True, or construct one directly.

from pinecone import Pinecone

pc = Pinecone(api_key="your-api-key")

# Resolve host automatically by index name
idx = pc.index("my-index", grpc=True)

# Or construct directly with a host URL
from pinecone.grpc import GrpcIndex
idx = GrpcIndex(host="my-index-abc123.svc.pinecone.io", api_key="your-api-key")

Method groups:

class pinecone.grpc.GrpcIndex(*, host, api_key=None, api_version='2026-07', source_tag=None, secure=True, grpc_scheme=None, timeout=20.0, connect_timeout=1.0, retry_config=None, proxy_url=None, on_throttle=None, limiter_registry=None)[source]

Bases: object

Synchronous gRPC data plane client targeting a specific Pinecone index.

Reach it as pc.index(name="article-search", grpc=True), which resolves the host for you, or construct it directly when you already know the host.

It offers the vector, namespace and import methods of Index (a document index needs Index.documents on the REST client) and is the one to reach for when throughput on a long ingest matters; on everything else Index is the better default, because gRPC has no asyncio twin and needs a compiled extension. Three differences are visible in the code you write: the *_async methods here return a PineconeFuture rather than something you await; retry_config.retryable_status_codes has no effect, since this transport retries gRPC status codes rather than HTTP ones; and upsert_records() and search() still travel over REST, because the gRPC API has no records operations. See Using the gRPC client.

Parameters:
  • host (str) – The index-specific data plane host, e.g. "article-search-abc123.svc.pinecone.io".

  • api_key (str | None) – Pinecone API key. Falls back to PINECONE_API_KEY env var.

  • api_version (str) – API version string. Defaults to the current data plane version.

  • source_tag (str | None) – Tag appended to the User-Agent string for request attribution.

  • secure (bool) – Whether the channel is given TLS material: system root certificates for gRPC, and certificate verification for the REST calls this client also makes. Defaults to True. It supplies the default for grpc_scheme, and grpc_scheme decides whether the wire is encrypted.

  • grpc_scheme (str | None) – URL scheme used to dial the data plane, "http" or "https". Set it when the data plane is reached over something other than public TLS (a plaintext gateway, an egress proxy, a private endpoint, or a local simulator) rather than leaving the SDK to assume one. None (default) reads the PINECONE_GRPC_SCHEME env var, then falls back to https when secure is True and http when it is False. "https" requires secure=True, since an https endpoint cannot connect without the TLS material secure=False withholds. "http" with secure=True is a plaintext channel: the scheme, not the TLS material, decides what goes on the wire. A resolved http scheme against a host outside loopback and the RFC 1918 private ranges warns once per process, because the API key and every payload then cross the network unencrypted.

  • timeout (float) – Deadline in seconds for a single attempt of a request, not for the call as a whole. Defaults to 20.0. A per-call timeout= does not replace it: the channel keeps this one too, so the shorter of the two governs.

  • connect_timeout (float) – Connection timeout in seconds. Defaults to 1.0.

  • retry_config (RetryConfig | None) – Retry policy for transient gRPC errors. Accepts the same RetryConfig REST uses. None (default) uses the gRPC defaults (max_retries=5, backoff_factor=0.1, max_wait=60.0), which differ from REST’s, so a retry_config you leave unset on Pinecone does not carry over here. Its retryable_status_codes field is ignored on this transport: it carries HTTP statuses, and the codes retried here are gRPC ones. See Retries and resilience.

  • proxy_url (str | None) – HTTP proxy URL, e.g. "http://proxy.internal:3128". gRPC traffic is tunnelled through it with HTTP CONNECT. Credentials in the URL, e.g. "http://user:pass@proxy.internal:3128", are percent-decoded and sent as Proxy-Authorization: Basic .... Only http:// proxies are supported: the CONNECT request always goes to the proxy in plaintext, so any other scheme (https://, socks5://, …) or a URL without a scheme raises PineconeValueError.

  • on_throttle (Callable[[str], None] | None) – Called with the bare host name each time a request fails with a retryable gRPC status, whether or not it is retried. Use it for observability, e.g. counting throttles per host; the SDK’s own backoff runs whether or not you set it. It may be called from any thread. None (default) falls back to retry_config.on_throttle.

  • limiter_registry (_AdaptiveLimiterRegistry | None) – SDK-internal. Registry the bulk paths consult to back off under throttling. Wired by index(); not intended for user configuration.

Raises:

PineconeValueError – If no API key can be resolved, the key is blank or contains a control or non-ASCII character (leading and trailing spaces and tabs are allowed and sent as given), the host is invalid, grpc_scheme names a scheme other than http or https, or grpc_scheme="https" is combined with secure=False, or proxy_url is not an http:// URL (gRPC does not support https:// or SOCKS proxies; REST does), has no host or an invalid port, has surrounding whitespace, or has an unencoded #, / or ? in the username or password.

Examples

import os

from pinecone import Pinecone

pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
idx = pc.index(name="article-search", grpc=True)

Construct it directly when you already know the host. A data plane fronted by a plaintext gateway or served by a local simulator is dialled over http by saying so:

from pinecone.grpc import GrpcIndex

idx = GrpcIndex(
    host="http://127.0.0.1:5085",
    api_key=os.environ["PINECONE_API_KEY"],
    grpc_scheme="http",
)

Note

Four timeout layers apply to every gRPC call, and only the first three bound a single request:

  1. Connect: connect_timeout.

  2. Per attempt: timeout, or a per-call timeout=. This is a deadline on one attempt, not on the call. Both apply when a call passes its own, so the shorter of the two is what fires.

  3. Retry budget: retry_config.max_retries attempts after the first, with backoff between them.

  4. Whole job: for bulk methods only, total_timeout.

Layers 2 and 3 compound only across retryable failures, and this transport retries exactly three gRPC status codes: UNAVAILABLE, RESOURCE_EXHAUSTED, and ABORTED. A lower max_retries shrinks the worst case, where every attempt uses nearly its full deadline and then fails with one of those.

An expiring deadline is not one of the three. Layer 2 firing raises PineconeTimeoutError after a single attempt, so max_retries is not the knob for a timeout. Raise timeout= to give the server longer per attempt (and the index-level timeout too, if it is the lower of the two), or bound a bulk job with total_timeout.

See also

__init__(*, host, api_key=None, api_version='2026-07', source_tag=None, secure=True, grpc_scheme=None, timeout=20.0, connect_timeout=1.0, retry_config=None, proxy_url=None, on_throttle=None, limiter_registry=None)[source]
Parameters:
  • host (str)

  • api_key (str | None)

  • api_version (str)

  • source_tag (str | None)

  • secure (bool)

  • grpc_scheme (Literal['http', 'https'] | None)

  • timeout (float)

  • connect_timeout (float)

  • retry_config (RetryConfig | None)

  • proxy_url (str | None)

  • on_throttle (Callable[[str], None] | None)

  • limiter_registry (_AdaptiveLimiterRegistry | None)

Return type:

None

property host: str

The data plane host URL for this index.

upsert(*, vectors, namespace='', batch_size=None, max_concurrency=8, show_progress=True, timeout=None, total_timeout=None)[source]

Upsert a batch of vectors into a namespace.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. A vector whose ID already exists in the namespace is overwritten. Each request is capped on both vector count and encoded size, and wide vectors or large metadata usually hit the size cap first, so pass batch_size to split a long sequence into requests that stay under both.

Parameters:
  • vectors (Sequence[Vector | tuple[str, Sequence[float]] | tuple[str, Sequence[float], Mapping[str, Any]] | Mapping[str, Any]]) – Vectors to upsert. Each element can be a Vector, a tuple of (id, values) or (id, values, metadata), or a dict with id, values, and optional sparse_values / metadata keys.

  • namespace (str) – Target namespace, e.g. "articles-en". Defaults to the index’s default namespace.

  • batch_size (int | None) – Split vectors into chunks of this size and send one request per chunk, e.g. 100. None (default) sends every vector in one request. Must be a positive integer.

  • show_progress (bool) – When True (default) and tqdm is installed, display a progress bar that advances as batches complete. No effect when batch_size is None.

  • max_concurrency (int) – Most batch requests this call keeps in flight at once, e.g. 16. Defaults to 8. Only used when batch_size is set. A process-wide limit per host also applies and holds concurrency lower when the host pushes back; see Bulk ingest.

  • timeout (float | None) – Timeout in seconds for one attempt of one request, e.g. 30.0. A batch is retried on its own under the client’s retry policy, so this does not bound the whole call. None (default) uses the client-level default.

  • total_timeout (float | None) – Deadline in seconds for the whole batched operation, e.g. 600.0. Only used when batch_size is set. On expiry no further batches are submitted, batches already in flight are awaited, and unsent batches are reported in failed_items. None (default) means no deadline. Zero or a negative value raises PineconeValueError.

Returns:

UpsertResponse with upserted_count. With batch_size set, a failed batch does not raise: has_errors, errors and failed_items report what did not land, and failed_items can be passed straight back to upsert().

Raises:
  • PineconeTypeError – If a vector element is not one of the forms listed above.

  • PineconeValueError – If a vector element is malformed, batch_size is not a positive integer, or max_concurrency is out of range.

  • ApiError – If batch_size is None and the request exceeds the server’s cap on vectors per request or on encoded size. Set a batch_size and retry.

Return type:

UpsertResponse

Examples

All three vector forms are interchangeable within one call. The values below are truncated to three floats for the page; pass your index’s full dimension.

from pinecone import Vector
from pinecone.grpc import GrpcIndex

idx = GrpcIndex(
    host="article-search-abc123.svc.pinecone.io",
    api_key="your-api-key",
)
response = idx.upsert(
    vectors=[
        Vector(id="article-101", values=[0.012, -0.087, 0.153]),
        ("article-102", [0.045, 0.021, -0.064]),
        {"id": "article-103", "values": [0.091, -0.032, 0.178]},
    ],
    namespace="articles-en",
)
print(response.upserted_count)

For a sequence too long for one request (embeddings below being your whole list of vectors), set batch_size and resend what did not land:

response = idx.upsert(
    vectors=embeddings,
    namespace="articles-en",
    batch_size=100,
)
if response.has_errors:
    idx.upsert(vectors=response.failed_items, namespace="articles-en")

See also

query(*, top_k, vector=None, id=None, namespace='', filter=None, include_values=False, include_metadata=False, sparse_vector=None, scan_factor=None, max_candidates=None, timeout=None)[source]

Query a namespace for the nearest neighbors of a vector you supply.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. You supply the query vector; nothing is embedded for you. Pass a dense vector, a sparse_vector, both for a hybrid query, or the id of a stored vector to use as the query.

Parameters:
  • top_k (int) – Number of results to return, e.g. 5. The server caps it.

  • vector (list[float] | None) – Dense query vector, at your index’s dimension.

  • id (str | None) – ID of a stored vector to use as the query, e.g. "article-101". Cannot be combined with vector or sparse_vector.

  • namespace (str) – Namespace to query, e.g. "articles-en". Defaults to the index’s default namespace.

  • filter (dict[str, Any] | None) – Metadata filter expression restricting which vectors are searched, e.g. {"year": {"$gte": 2020}}.

  • include_values (bool) – Return each match’s vector values. False (default) keeps the response small.

  • include_metadata (bool) – Return each match’s metadata. Set it when you need the fields you filtered on back in the result.

  • sparse_vector (SparseValues | dict[str, Any] | None) – Sparse query vector with indices and values, e.g. {"indices": [17, 42], "values": [0.4, 0.9]}. Combine it with vector for a hybrid query on a dense index with the dotproduct metric.

  • scan_factor (float | None) – Recall/latency trade for dense indexes on dedicated read nodes: a multiplier on how much of the index is scanned. Above 1 scans more and favors recall; below 1 scans less and favors latency. Omit to let the server choose.

  • max_candidates (int | None) – Recall/latency trade for dense indexes on dedicated read nodes: caps how many candidates are reranked before top_k is taken. Must be at least top_k.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

QueryResponse with matches (ordered from most to least similar, each carrying id and score), namespace, and usage.

Raises:
  • PineconeValueError – If top_k is not positive or exceeds the server’s maximum, if id is combined with vector or sparse_vector, if none of vector, id, or sparse_vector is given, or if id is not a legal vector ID. Raised before any request is sent.

  • ApiError – If scan_factor or max_candidates is set on an index that does not run on dedicated read nodes, or on a sparse index.

Return type:

QueryResponse

Examples

Query vectors are truncated to three floats on this page; pass your index’s full dimension.

response = idx.query(
    top_k=5,
    vector=[0.012, -0.087, 0.153],
    namespace="articles-en",
)
for match in response.matches:
    print(match.id, match.score)

A filter narrows the search before ranking, and include_metadata returns the fields it selected on:

response = idx.query(
    top_k=5,
    vector=[0.012, -0.087, 0.153],
    namespace="movies-en",
    filter={"genre": "comedy", "year": {"$gte": 2020}},
    include_metadata=True,
)
for match in response.matches:
    print(match.id, match.score, match.metadata["genre"])

See also

  • search(): the same search on a legacy integrated index, where you pass text and the server embeds it.

  • query_namespaces(): the same query fanned out over several namespaces, merged into one ranking.

query_namespaces(*, vector=None, namespaces, metric, top_k=None, filter=None, include_values=False, include_metadata=False, sparse_vector=None, scan_factor=None, max_candidates=None, timeout=None)[source]

Query several namespaces at once and merge them into one ranking.

Serves indexes created with dimension/metric and legacy integrated indexes. Runs one query() per namespace concurrently, then merges the results so you get the overall top-k rather than top-k per namespace. The merge ranks by metric, which the client does not read off the index, so pass the metric the index was created with.

Parameters:
  • vector (list[float] | None) – Dense query vector. Omit it on a sparse index and pass sparse_vector instead.

  • namespaces (list[str]) – Namespaces to query, e.g. ["articles-en", "articles-fr"]. Must be non-empty; duplicates are removed while preserving order.

  • metric (str) – Metric the index was created with: "cosine", "euclidean", or "dotproduct". A wrong metric is not rejected; the merged ranking just comes out in the wrong order.

  • top_k (int | None) – Number of results to return after merging, e.g. 10. Defaults to 10. Each namespace is queried for this many.

  • filter (dict[str, Any] | None) – Metadata filter expression applied to every namespace, e.g. {"year": {"$gte": 2020}}.

  • include_values (bool) – Return each match’s vector values.

  • include_metadata (bool) – Return each match’s metadata.

  • sparse_vector (SparseValues | dict[str, Any] | None) – Sparse query vector with indices and values. Required on a sparse index, where vector is omitted.

  • scan_factor (float | None) – Recall/latency trade for dense indexes on dedicated read nodes, applied to every namespace. See query().

  • max_candidates (int | None) – Candidate cap for dense indexes on dedicated read nodes, applied per namespace. Must be at least top_k.

  • timeout (float | None) – Per-request timeout in seconds, applied to each namespace’s query rather than to the call as a whole.

Returns:

QueryNamespacesResults with the merged matches, usage totalled over every namespace, and ns_usage keyed by namespace name. A match does not record which namespace produced it, so query one namespace at a time when you need that.

Raises:
  • PineconeValueError – If namespaces is empty, if both vector and sparse_vector are absent or empty, or if metric is not one of "cosine", "euclidean", or "dotproduct". Raised before any request is sent.

  • ApiError – If any one namespace’s query fails. The first failure propagates and the merged result is lost, so retry the whole call.

Return type:

QueryNamespacesResults

Examples

The query vector is truncated to three floats on this page; pass your index’s full dimension.

results = idx.query_namespaces(
    vector=[0.012, -0.087, 0.153],
    namespaces=["articles-en", "articles-fr", "articles-de"],
    metric="cosine",
    top_k=10,
)
for match in results.matches:
    print(match.id, match.score)

On a sparse index, pass sparse_vector instead and rank by "dotproduct":

results = idx.query_namespaces(
    sparse_vector={"indices": [17, 42, 108], "values": [0.4, 0.9, 0.2]},
    namespaces=["articles-en", "articles-fr"],
    metric="dotproduct",
    top_k=10,
)

See also

query(): one namespace, and the only form that takes an id as the query.

fetch(*, ids, namespace='', timeout=None)[source]

Fetch vectors by their IDs, exactly as stored.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. A lookup, not a search: nothing is ranked and no score is returned. An ID that is not in the namespace is silently absent from the result, so compare the keys you got back against the ones you asked for.

Parameters:
  • ids (list[str]) – Vector IDs to fetch, e.g. ["article-101", "article-102"]. Must be non-empty.

  • namespace (str) – Namespace to fetch from, e.g. "articles-en". Defaults to the index’s default namespace.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

FetchResponse with vectors, a map of ID to Vector holding values and metadata as stored, plus namespace and usage. IDs the namespace does not hold are absent from the map rather than raising.

Raises:

PineconeValueError – If ids is empty or holds an ID that is empty, non-ASCII, contains a NUL, or is longer than the API allows. Raised before any request is sent.

Return type:

FetchResponse

Examples

wanted = ["article-101", "article-102"]
response = idx.fetch(ids=wanted, namespace="articles-en")
for vid, vec in response.vectors.items():
    print(vid, vec.metadata)
print("not in this namespace:", set(wanted) - set(response.vectors))

See also

  • fetch_by_metadata(): when you know the metadata you want rather than the IDs.

  • query(): when you want the nearest vectors rather than named ones.

fetch_by_metadata(*, filter, namespace='', limit=None, pagination_token=None, timeout=None)[source]

Fetch one page of the vectors whose metadata matches a filter.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. A lookup, not a search: matches are not ranked and carry no score. One page is returned per call, so follow pagination.next to reach the rest.

Parameters:
  • filter (dict[str, Any]) – Metadata filter expression, e.g. {"year": {"$gte": 2020}}. Must carry at least one condition; an empty filter is rejected rather than treated as “match everything”.

  • namespace (str) – Namespace to fetch from, e.g. "movies-en". Defaults to the index’s default namespace.

  • limit (int | None) – Maximum number of vectors in this page, e.g. 100. Omit to let the server choose the page size.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

FetchByMetadataResponse with vectors as stored, plus namespace, usage, and pagination, which holds the next page’s token in next and is None on the last page.

Raises:

PineconeValueError – If filter is empty or limit is not a positive integer within the API’s maximum page size. Raised before any request is sent.

Return type:

FetchByMetadataResponse

Examples

response = idx.fetch_by_metadata(
    filter={"genre": "comedy", "year": {"$gte": 2020}},
    namespace="movies-en",
)
for vid, vec in response.vectors.items():
    print(vid, vec.metadata)

See also

  • fetch(): when you already know the IDs.

  • query(): when you want the nearest vectors to a query rather than every vector a filter admits.

  • Pagination: walking every page.

delete(*, ids=None, delete_all=False, filter=None, namespace='', timeout=None)[source]

Delete vectors from a namespace by ID, by filter, or all of them.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. Pass exactly one selector: ids, filter, or delete_all=True. The delete is irreversible, and IDs the namespace does not hold are ignored rather than reported, so a successful call is not evidence anything was deleted.

Parameters:
  • ids (list[str] | None) – Vector IDs to delete, e.g. ["article-101", "article-102"].

  • delete_all (bool) – Delete every vector in namespace. The namespace itself survives; delete_namespace() removes that too.

  • filter (dict[str, Any] | None) – Metadata filter expression selecting what to delete, e.g. {"status": {"$eq": "retracted"}}. Must carry at least one condition. The client refuses ids alongside filter, because the server would apply the filter alone and delete everything it matches rather than the intersection; to delete the intersection, query() with the filter first and delete the IDs you get back.

  • namespace (str) – Namespace to delete from, e.g. "articles-en". Defaults to the index’s default namespace.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

None. A successful delete returns no payload.

Raises:

PineconeValueError – If zero or more than one selector is given, if filter is empty, or if an ID is not a legal vector ID. Raised before any request is sent.

Return type:

None

Examples

By ID:

idx.delete(
    ids=["article-101", "article-102"],
    namespace="articles-en",
)

By metadata filter, which deletes every vector the filter admits:

idx.delete(
    filter={"status": {"$eq": "retracted"}},
    namespace="articles-en",
)

Emptying a whole namespace cannot be undone:

idx.delete(delete_all=True, namespace="articles-staging")

See also

delete_namespace(): removes the namespace along with everything in it, where delete_all=True empties it and leaves it in place.

update(*, id=None, values=None, sparse_values=None, set_metadata=None, namespace='', filter=None, dry_run=False, timeout=None)[source]

Patch one vector by ID, or patch metadata across a filter.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. A partial update: fields you do not mention keep the values they had, so set_metadata={"year": 2021} leaves every other metadata key in place. Pass exactly one selector, id or filter; a by-filter update is metadata-only, since values and sparse_values belong to one record. The write applies asynchronously, so a read straight afterwards can still see the old value.

Parameters:
  • id (str | None) – ID of the one vector to patch, e.g. "article-101".

  • values (list[float] | None) – Replacement dense values, at your index’s dimension. Only with id.

  • sparse_values (SparseValues | dict[str, Any] | None) – Replacement sparse vector, with indices and values. Only with id.

  • set_metadata (dict[str, Any] | None) – Metadata keys to set or overwrite, e.g. {"year": 2021}. Keys you omit are left as they are; this never clears a field.

  • namespace (str) – Namespace to target, e.g. "movies-en". Defaults to the index’s default namespace.

  • filter (dict[str, Any] | None) – Metadata filter expression selecting which vectors to patch, e.g. {"genre": {"$eq": "drama"}}. Must carry at least one condition.

  • dry_run (bool) – Report how many records the filter would touch without writing anything. Ignored for a by-ID update. Run it first when the filter is broader than you can check by eye.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

UpdateResponse whose matched_records counts the records the filter matched, which under dry_run are the records that would have been patched. It is None for a by-ID update, which reports no count.

Raises:

PineconeValueError – If both or neither of id and filter are given, if filter is combined with values or sparse_values, if filter is empty, or if id is not a legal vector ID. Raised before any request is sent.

Return type:

UpdateResponse

Examples

Replacing one vector’s values, truncated here to three floats:

idx.update(
    id="article-101",
    values=[0.012, -0.087, 0.153],
    namespace="articles-en",
)

Patching metadata across a filter. dry_run reports the reach first, and the genre of every patched record survives untouched:

preview = idx.update(
    filter={"genre": {"$eq": "drama"}},
    set_metadata={"reviewed": True},
    namespace="movies-en",
    dry_run=True,
)
print(preview.matched_records)
idx.update(
    filter={"genre": {"$eq": "drama"}},
    set_metadata={"reviewed": True},
    namespace="movies-en",
)

See also

upsert(): replaces a whole vector rather than patching it, and creates it if the ID is new.

list_paginated(*, prefix=None, limit=None, pagination_token=None, namespace='', timeout=None)[source]

Fetch one page of vector IDs, holding the pagination token yourself.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. Returns IDs only, without values or metadata. list() walks the pages for you; use this one when you need to keep the token between calls.

Parameters:
  • prefix (str | None) – Return only IDs starting with this prefix, e.g. "article-2024#". Must be ASCII, without a NUL character, and no longer than the API allows. The empty prefix matches everything.

  • limit (int | None) – Maximum number of IDs in this page, e.g. 50. Must be a positive integer within the API’s maximum page size. None uses the server’s default page size.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

  • namespace (str) – Namespace to list from, e.g. "articles-en". Defaults to the default namespace.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

ListResponse whose vectors are ListItem entries carrying only an id, plus namespace, usage, and pagination. pagination.next is the token for the following page; the last page carries no token.

Raises:

PineconeValueError – If prefix or limit is not legal. Raised before any request is sent.

Return type:

ListResponse

Examples

response = idx.list_paginated(
    prefix="article-2024#",
    limit=50,
    namespace="articles-en",
)
for item in response.vectors:
    print(item.id)
next_token = response.pagination.next if response.pagination else None

See also

  • list(): the same listing with the token handled for you.

  • fetch(): the vectors behind those IDs.

  • Pagination: how the SDK pages generally.

list(*, prefix=None, limit=None, namespace='', timeout=None)[source]

List vector IDs in a namespace, a page at a time.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. Returns IDs only, without values or metadata. Yields one page per iteration and follows the pagination tokens itself. Nothing is requested until you iterate, so a bad prefix or limit is not reported until then either.

Parameters:
  • prefix (str | None) – Return only IDs starting with this prefix, e.g. "article-2024#". Must be ASCII, without a NUL character, and no longer than the API allows. The empty prefix matches everything.

  • limit (int | None) – Maximum number of IDs per page, e.g. 50. Must be a positive integer within the API’s maximum page size. None uses the server’s default page size.

  • namespace (str) – Namespace to list from, e.g. "articles-en". Defaults to the default namespace.

  • timeout (float | None) – Per-request timeout in seconds, applied to each underlying page request. Overrides the client-level default for this call only.

Yields:

ListResponse per page, whose vectors carry the IDs. A page with no IDs is skipped rather than yielded.

Raises:

PineconeValueError – If prefix or limit is not legal. Raised on first iteration, not at the call.

Return type:

Iterator[ListResponse]

Examples

for page in idx.list(prefix="article-2024#", namespace="articles-en"):
    ids = [item.id for item in page.vectors]
    fetched = idx.fetch(ids=ids, namespace="articles-en")
    for vid, vec in fetched.vectors.items():
        print(vid, vec.metadata)

See also

describe_index_stats(*, filter=None, timeout=None)[source]

Report vector counts per namespace, dimension, and fullness for this index.

Works on every kind of index, including document indexes. The counts lag writes, so a record just upserted may not be counted yet.

Parameters:
  • filter (dict[str, Any] | None) – Accepted for API compatibility only. The server rejects a non-empty filter, so leave it unset; the statistics always describe the whole index.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

DescribeIndexStatsResponse with total_vector_count, dimension, index_fullness, and namespaces, which maps each namespace name to a NamespaceSummary carrying its vector_count. The default namespace appears under "__default__".

Raises:

ApiError – If filter is non-empty.

Return type:

DescribeIndexStatsResponse

Examples

stats = idx.describe_index_stats()
print(stats.dimension, stats.index_fullness)
for name, summary in stats.namespaces.items():
    print(name, summary.vector_count)

See also

list_namespaces(): per-namespace record counts alongside each namespace’s schema and size_bytes.

upsert_from_dataframe(df, namespace='', batch_size=500, show_progress=True, timeout=None, *, max_concurrency=None, total_timeout=None, on_error=None)[source]

Upsert vectors from a pandas DataFrame, in batches.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use Index.documents on the REST client instead. Each row becomes one vector, and every row is validated before the first batch is sent, so a malformed row cannot leave part of the frame ingested. A batch that fails is reported on the response rather than raised unless you pass on_error="raise". pandas is not an SDK dependency; install it yourself.

Parameters:
  • df (pd.DataFrame) – A pandas.DataFrame with id and values columns and, optionally, sparse_values and metadata columns. A missing cell (None or NaN) in an optional column leaves that field off the vector.

  • namespace (str) – Target namespace, e.g. "articles-en". Defaults to the index’s default namespace.

  • batch_size (int) – Rows per upsert request, e.g. 100. Defaults to 500. Lower it for wide vectors or large metadata.

  • show_progress (bool) – When True (default) and tqdm is installed, display a progress bar that advances as batches complete.

  • timeout (float | None) – Deadline in seconds for one attempt of one batch, e.g. 120.0. A batch that keeps failing on a retryable code is retried, so its wall-clock time can exceed this, but an attempt that runs out of time is not retried: raise timeout, not max_retries, to fix a timeout. None (default) uses the timeout the index was constructed with. See the timeout layers on GrpcIndex and Retries and resilience.

  • max_concurrency (int | None) – Most batch requests this call keeps in flight at once, e.g. 16. None (default) uses 8. A process-wide limit per host also applies and holds concurrency lower when the host pushes back; see Bulk ingest.

  • total_timeout (float | None) – Deadline in seconds for the whole ingest, e.g. 600.0. On expiry no further batches are submitted, batches already in flight are awaited (dropping them client-side would not stop the server from applying them), and unsent rows are reported in failed_items. None (default) means no deadline. Zero or a negative value raises PineconeValueError.

  • on_error (str | None) – What to do when some batches fail. "collect" returns the response with errors and failed_items filled in. This holds when every batch fails too: nothing raises, so check response.has_errors. "raise" raises the lowest-indexed batch failure, or PineconeTimeoutError when total_timeout expired, once every batch has settled, with the partial response on the exception’s response attribute. None (default) behaves as "collect" and also warns once per process on a partial failure, because this method raised before 10.0; pass "collect" to silence the warning.

Returns:

UpsertResponse with upserted_count totalled across the batches that landed, plus has_errors, errors and failed_items for the ones that did not. failed_items can be passed straight back to upsert().

Raises:
  • RuntimeError – If pandas is not installed.

  • PineconeValueError – If df is not a pandas.DataFrame or lacks an id or values column, a row is malformed, batch_size is not a positive integer, max_concurrency is out of range, or on_error is not "collect" or "raise".

  • PineconeTimeoutError – If on_error="raise" and a batch timed out or total_timeout expired.

Return type:

UpsertResponse

Examples

A metadata column is optional; where it is present its dict lands on the vector as written. The values below are truncated to three floats for the page; pass your index’s full dimension.

import pandas as pd
from pinecone.grpc import GrpcIndex

idx = GrpcIndex(
    host="article-search-abc123.svc.pinecone.io",
    api_key="your-api-key",
)
df = pd.DataFrame([
    {
        "id": "article-101",
        "values": [0.012, -0.087, 0.153],
        "metadata": {"topic": "science", "year": 2024},
    },
    {
        "id": "article-102",
        "values": [0.045, 0.021, -0.064],
        "metadata": {"topic": "technology", "year": 2024},
    },
])
response = idx.upsert_from_dataframe(
    df,
    namespace="articles-en",
    batch_size=100,
)
if response.has_errors:
    idx.upsert(vectors=response.failed_items, namespace="articles-en")

See also

  • upsert(): the same batched write from a list of vectors, with no pandas dependency.

  • start_import(): millions of vectors from cloud storage, server-side and asynchronous.

Changed in version 10.0: Partial failures are aggregated into the response rather than raised, matching upsert() with batch_size and the REST client. Pass on_error="raise" to keep the previous behavior. See gRPC partial failures.

upsert_async(*, vectors, namespace='', timeout=None)[source]

Send one upsert request without waiting for it.

A narrower upsert(): it sends exactly one request, so there is no batch_size and none of the batching arguments that go with it. To overlap several requests, issue several of these and collect the futures.

Parameters:
Returns:

PineconeFuture resolving to an UpsertResponse. Its result() raises whatever upsert() would have raised.

Return type:

PineconeFuture[UpsertResponse]

Examples

future = idx.upsert_async(
    vectors=[("article-101", [0.012, -0.087, 0.153])],
    namespace="articles-en",
)
print(future.result().upserted_count)
query_async(*, top_k, vector=None, id=None, namespace='', filter=None, include_values=False, include_metadata=False, sparse_vector=None, scan_factor=None, max_candidates=None, timeout=None)[source]

Send one query without waiting for it, as query() otherwise would.

Takes the same arguments as query(); only the return type differs. Reach for it to have several queries in flight at once, over different namespaces or with different filters.

Returns:

PineconeFuture resolving to a QueryResponse. Its result() raises whatever query() would have raised.

Parameters:
Return type:

PineconeFuture[QueryResponse]

Examples

future = idx.query_async(
    vector=[0.012, -0.087, 0.153],
    top_k=5,
    namespace="articles-en",
)
for match in future.result().matches:
    print(match.id, match.score)
fetch_async(*, ids, namespace='', timeout=None)[source]

Send one fetch without waiting for it, as fetch() otherwise would.

Takes the same arguments as fetch(); only the return type differs. Reach for it to fetch from several namespaces at once.

Returns:

PineconeFuture resolving to a FetchResponse. Its result() raises whatever fetch() would have raised.

Parameters:
Return type:

PineconeFuture[FetchResponse]

Examples

future = idx.fetch_async(
    ids=["article-101", "article-102"],
    namespace="articles-en",
)
for vid, vec in future.result().vectors.items():
    print(vid, len(vec.values))
delete_async(*, ids=None, delete_all=False, filter=None, namespace='', timeout=None)[source]

Send one delete without waiting for it, as delete() otherwise would.

Takes the same arguments as delete(); only the return type differs. The delete is sent as soon as a worker thread picks it up. Dropping the future does not stop it, and PineconeFuture.cancel() succeeds only before that.

Returns:

PineconeFuture resolving to None once the server accepts the delete. Collect it anyway: its result() raises whatever delete() would have raised.

Parameters:
Return type:

PineconeFuture[None]

Examples

future = idx.delete_async(
    ids=["article-101", "article-102"],
    namespace="articles-en",
)
future.result()
update_async(*, id=None, values=None, sparse_values=None, set_metadata=None, filter=None, namespace='', dry_run=False, timeout=None)[source]

Send one update without waiting for it, as update() otherwise would.

Takes the same arguments as update(); only the return type differs.

Returns:

PineconeFuture resolving to an UpdateResponse. Its result() raises whatever update() would have raised.

Parameters:
Return type:

PineconeFuture[UpdateResponse]

Examples

future = idx.update_async(
    id="article-101",
    values=[0.012, -0.087, 0.153],
    namespace="articles-en",
)
future.result()
query_namespaces_async(*, vector=None, namespaces, metric, top_k=None, filter=None, include_values=False, include_metadata=False, sparse_vector=None, scan_factor=None, max_candidates=None, timeout=None)[source]

Start a query_namespaces() fan-out without waiting for it.

Takes the same arguments as query_namespaces(); only the return type differs. query_namespaces() already queries the namespaces concurrently, so this is worth it only to overlap the whole fan-out with other work.

Returns:

PineconeFuture resolving to a QueryNamespacesResults. Its result() raises whatever query_namespaces() would have raised.

Parameters:
Return type:

PineconeFuture[QueryNamespacesResults]

Examples

future = idx.query_namespaces_async(
    vector=[0.012, -0.087, 0.153],
    namespaces=["articles-en", "articles-fr", "articles-de"],
    metric="cosine",
    top_k=10,
)
for match in future.result(timeout=30.0).matches:
    print(match.id, match.score)
upsert_records(*, records, namespace, timeout=None)[source]

Upsert text records into a legacy integrated index (legacy Records API).

Serves legacy integrated indexes, created with create_for_model(): the server embeds each record’s text with the index’s model. On a document index use the REST client’s Index.documents instead. Upserts apply asynchronously, so a record may not be searchable immediately.

GrpcIndex sends this call over REST, because the gRPC API has no records operations.

Parameters:
  • records (list[dict[str, Any]]) – Records to write, each with an _id (or id) string plus the fields to store, e.g. {"_id": "article-101", "text": "Vector databases for search."}. The index embeds the field its embed configuration maps and stores the rest with the record.

  • namespace (str) – Target namespace, e.g. "articles-en". Required: the legacy Records API has no implicit default namespace, so pass "__default__" to write to it.

  • timeout (float | None) – Per-request timeout in seconds, e.g. 10.0. None uses the timeout the index was constructed with.

Returns:

UpsertRecordsResponse whose record_count is the number of records the client sent.

Raises:

PineconeValueError – If namespace is not a non-empty string, records is empty, or a record has no _id/id field. Raised before any request is made.

Return type:

UpsertRecordsResponse

Examples

idx = pc.index(name="article-search", grpc=True)
response = idx.upsert_records(
    namespace="articles-en",
    records=[
        {"_id": "article-101", "text": "Vector databases for search."},
        {"_id": "article-102", "text": "RAG combines search with LLMs."},
    ],
)
print(response.record_count)

See also

  • search(): the read side of a legacy integrated index.

  • upsert(): write vectors you embedded yourself.

search(*, namespace, top_k=None, inputs=None, vector=None, id=None, filter=None, fields=None, rerank=None, match_terms=None, query=None, timeout=None)[source]

Search records by text, vector, or ID, optionally reranking (legacy Records API).

Give exactly one query source. Text in inputs needs a legacy integrated index, created with create_for_model(), whose model embeds it server-side. A vector or id query also works on an index created with dimension/metric, though query() is the usual call there. On a document index use the REST client’s Index.documents instead.

GrpcIndex sends this call over REST, because the gRPC API has no records search, so it retries on the REST data plane’s fixed terms rather than the retry_config passed to GrpcIndex; see Retries and resilience.

Parameters:
  • namespace (str) – Namespace to search, e.g. "articles-en". Required: pass "__default__" to search the default namespace.

  • top_k (int) – Number of results to return, at least 1, e.g. 10. Required unless query is given.

  • inputs (SearchInputs | dict[str, Any] | None) – Text for the index’s model to embed, e.g. {"text": "trail running shoes"}. SearchInputs gives typed keys and IDE completion.

  • vector (list[float] | dict[str, Any] | None) – Query vector. A list[float] is a dense query; a dict with values, sparse_indices and/or sparse_values is a sparse or hybrid one. SearchQueryVector is the typed helper.

  • id (str | None) – ID of a stored record whose vector is the query, e.g. "article-101".

  • filter (dict[str, Any] | None) – Metadata filter, e.g. {"category": {"$eq": "footwear"}}.

  • fields (list[str] | None) – Record fields to return in each hit, e.g. ["title", "text"]. None returns every stored field.

  • rerank (RerankConfig | dict[str, Any] | None) – Rerank the hits in the same call. Needs model and rank_fields; top_n, parameters and query are optional. RerankConfig gives IDE completion.

  • match_terms (dict[str, Any] | None) – Require hits to contain query terms, e.g. {"strategy": "all", "terms": ["running", "shoes"]}. Valid only with inputs, on a sparse index whose model supports it; the server names the supported model when it refuses.

  • timeout (float | None) – Per-request timeout in seconds, e.g. 10.0. None uses the timeout the index was constructed with.

  • query (SearchQuery | dict[str, Any] | None) – The older nested form of this call: top_k plus one query source in one mapping. Pass the fields directly instead.

Returns:

SearchRecordsResponse whose result.hits run from most to least relevant. Read each Hit as hit.id, hit.score and hit.fields. usage reports read units, plus embedding tokens and rerank units when those stages ran.

Raises:
  • PineconeValueError – If namespace is not a non-empty string, top_k is missing or below 1, no query source is given, a vector dict has an unsupported key, or rerank lacks model or rank_fields. Raised before any request is made.

  • TypeError – If query is combined with any of the flat keyword arguments it replaces (top_k, inputs, vector, id, filter, match_terms), so pass one form or the other, not both; or if query is neither a SearchQuery nor a mapping.

Return type:

SearchRecordsResponse

Examples

Text in, embedded server-side. The hits nest one level down, under result:

idx = pc.index(name="article-search", grpc=True)
response = idx.search(
    namespace="articles-en",
    top_k=10,
    inputs={"text": "benefits of vector databases for search"},
    fields=["title", "text"],
)
for hit in response.result.hits:
    print(hit.id, hit.score, hit.fields["title"])

Reranking in the same call retrieves top_k hits and returns the top_n the reranker scores highest:

response = idx.search(
    namespace="articles-en",
    top_k=50,
    inputs={"text": "benefits of vector databases"},
    rerank={
        "model": "bge-reranker-v2-m3",
        "rank_fields": ["text"],
        "top_n": 5,
    },
)

See also

  • query(): search with a vector you embedded yourself.

  • Inference.rerank(): rerank results that came from somewhere other than this index.

search_records(*, namespace, top_k=None, inputs=None, vector=None, id=None, filter=None, fields=None, rerank=None, match_terms=None, query=None, timeout=None)[source]

Alias for search() (legacy Records API), kept for callers written against 9.x.

Every argument, return value and error is search()’s. Call that one in new code.

Parameters:
Return type:

SearchRecordsResponse

list_namespaces_paginated(*, prefix=None, limit=None, pagination_token=None, timeout=None)[source]

Fetch one page of namespace descriptions, holding the token yourself.

list_namespaces() walks the pages for you; reach for this one when you need to persist the token between calls or hand it to a caller of your own.

Parameters:
  • prefix (str | None) – Return only namespaces whose names start with this prefix, e.g. "movies-". Same character rules as namespace names; the empty prefix matches every namespace.

  • limit (int | None) – Maximum number of namespaces in this page, e.g. 50. None (default) lets the server choose.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

  • timeout (float | None) – Per-call timeout in seconds.

Returns:

ListNamespacesResponse with namespaces (each a NamespaceDescription), total_count across every page, and pagination, whose next is None on the last page.

Raises:

PineconeValueError – If prefix or limit is out of range. Raised before any request is sent.

Return type:

ListNamespacesResponse

Examples

response = idx.list_namespaces_paginated(prefix="movies-", limit=10)
for ns in response.namespaces:
    print(ns.name, ns.record_count, ns.size_bytes)
next_token = response.pagination.next if response.pagination else None

See also

list_namespaces(*, prefix=None, limit=None, timeout=None)[source]

List every namespace, a page at a time.

Yields one ListNamespacesResponse per page and follows the pagination tokens itself, so nothing is requested until you iterate. Each page describes many namespaces in one request, so prefer this over repeated describe_namespace() calls, which are rate limited per index.

Parameters:
  • prefix (str | None) – Return only namespaces whose names start with this prefix, e.g. "movies-". Same character rules as namespace names; the empty prefix matches every namespace.

  • limit (int | None) – Maximum number of namespaces per page, e.g. 50. None (default) lets the server choose.

  • timeout (float | None) – Per-call timeout in seconds.

Yields:

ListNamespacesResponse per page, each carrying namespaces of NamespaceDescription. A page with no namespaces is skipped rather than yielded.

Raises:

PineconeValueError – If prefix or limit is out of range. Raised on first iteration, not at the call.

Return type:

Iterator[ListNamespacesResponse]

Examples

for page in idx.list_namespaces(prefix="movies-"):
    for ns in page.namespaces:
        print(ns.name, ns.record_count, ns.size_bytes)

See also

create_namespace(*, name, schema=None, timeout=None)[source]

Create a named namespace in the index.

Optional: upserting into a name that does not exist yet creates the namespace. Create one explicitly when it must exist before any data lands in it, or to choose which metadata fields it indexes. Not idempotent: an existing name raises ConflictError.

Parameters:
  • name (str) – Name for the new namespace, e.g. "movies-en". Must be non-empty ASCII without the NUL character, and no longer than the API’s maximum name length. __default__ is reserved and cannot be created. On an index created with dimension/metric it names the namespace requests address when they omit one, which always exists; on a document index, upserting documents into __default__ creates it.

  • schema (dict[str, Any] | None) – Optional metadata-index configuration, {"fields": {<field>: {"filterable": True}}}. Omitting it does not mean “index everything”: the namespace inherits the index’s own metadata-index configuration. Supply schema to index exactly the fields listed in this namespace. Each field must set filterable to True; to leave a field unindexed, omit it from fields.

  • timeout (float | None) – Per-call timeout in seconds.

Returns:

NamespaceDescription with the namespace name, record_count, schema, indexed_fields and size_bytes.

Raises:
  • PineconeValueError – If name violates the rules above, or schema is malformed. Raised before any request is sent.

  • ConflictError – a namespace of that name already exists.

Return type:

NamespaceDescription

Examples

ns = idx.create_namespace(name="movies-en")
print(ns.name, ns.record_count, ns.size_bytes)

Naming the filterable fields up front overrides what the namespace would otherwise inherit from the index:

ns = idx.create_namespace(
    name="movies-fr",
    schema={"fields": {"genre": {"filterable": True}}},
)
print(ns.indexed_fields)

See also

describe_namespace(*, name=None, timeout=None, **kwargs)[source]

Describe a namespace by name.

Rate limited per index. To describe more than one namespace, use list_namespaces(), which returns a whole page of descriptions per request.

Parameters:
  • name (str) – Name of the namespace to describe, e.g. "movies-en". Must be non-empty ASCII without the NUL character, and no longer than the API’s maximum name length. On an index created with dimension/metric, pass __default__ to describe the namespace requests address when they omit one. On a document index __default__ is an ordinary name, so describing it raises NotFoundError until documents are upserted into it.

  • timeout (float | None) – Per-call timeout in seconds.

  • kwargs (str)

Returns:

NamespaceDescription with the namespace name, record_count, schema, indexed_fields and size_bytes. size_bytes is approximate.

Raises:
  • PineconeValueError – If name violates the rules above. Raised before any request is sent.

  • TypeError – If unexpected keyword arguments are passed.

  • NotFoundError – no namespace of that name exists on the index.

  • ApiError – with status_code 429 when this operation’s per-index limit was exceeded. Use list_namespaces() to describe many namespaces.

Return type:

NamespaceDescription

Examples

ns = idx.describe_namespace(name="movies-en")
print(ns.name, ns.record_count, ns.size_bytes)

On an index created with dimension/metric, the namespace that unnamespaced requests address answers to __default__:

ns = idx.describe_namespace(name="__default__")
print(ns.record_count)

See also

list_namespaces(): every namespace, a page of descriptions per request.

delete_namespace(*, name=None, timeout=None, **kwargs)[source]

Delete a namespace and everything in it.

Irreversible: every record in the namespace is deleted, and the namespace itself stops existing. To empty a namespace but keep it, use delete() with delete_all=True.

Parameters:
  • name (str) – Name of the namespace to delete, e.g. "movies-deprecated". Must be non-empty ASCII without the NUL character, and no longer than the API’s maximum name length.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

  • kwargs (str)

Returns:

None. A successful delete returns no payload.

Raises:
  • PineconeValueError – If name violates the rules above. Raised before any request is sent.

  • TypeError – If unexpected keyword arguments are passed.

  • NotFoundError – no namespace of that name exists on the index.

Return type:

None

Examples

idx.delete_namespace(name="movies-deprecated")

See also

delete(): delete_all=True empties a namespace and leaves it in place.

start_import(uri, *, error_mode=None, integration_id=None)[source]

Start a server-side bulk import of vectors from cloud storage.

Returns as soon as the server accepts the import, not when it finishes: poll describe_import() for the outcome. Imports work on indexes created with dimension/metric and on document indexes; the server refuses them on an index with integrated embedding (a legacy integrated index, or a document index with an embed field).

Parameters:
  • uri (str) – Directory prefix holding the Parquet files, not a single file. Three forms are accepted: s3:// for Amazon S3, gs:// for Google Cloud Storage, and an https:// URL naming an Azure Blob Storage container. s3:// additionally requires that the index itself be hosted on AWS.

  • error_mode (str | None) – How to handle a record the import cannot read. "continue" skips it and imports the rest; "abort" ends the whole import at the first such record. Case-insensitive. Defaults to "abort" when omitted, so an unreadable record fails the import unless you opt into skipping.

  • integration_id (str | None) – ID of a storage integration in your project that grants Pinecone read access to a private bucket. Its cloud provider must match the scheme of uri.

Returns:

StartImportResponse with id, the handle the other import methods take.

Raises:
  • PineconeValueError – If error_mode is supplied but is neither "continue" nor "abort". Raised before any HTTP request is made.

  • ApiError – If the server rejects uri (for example, an s3:// URI on an index not hosted on AWS) or the index uses integrated embedding.

Return type:

StartImportResponse

Examples

The call returns as soon as the import is accepted, so poll describe_import() for the outcome:

import time

response = idx.start_import(uri="s3://acme-exports/articles/")
import_op = idx.describe_import(response.id)
while import_op.status not in ("Completed", "Failed", "Cancelled"):
    time.sleep(10)
    import_op = idx.describe_import(response.id)
print(import_op.status, import_op.records_imported)

Skip unreadable records rather than failing the whole import:

response = idx.start_import(
    uri="s3://acme-exports/articles/",
    error_mode="continue",
)

Note

uri must name a directory of Parquet files following Pinecone’s import schema. See the import guide for that schema and the supported storage formats.

See also

describe_import(id)[source]

Describe a bulk import operation by ID.

Parameters:

id (str | int) – The id start_import() returned, e.g. "1". An int is accepted and converted to a string.

Returns:

ImportModel with status ("Pending", "InProgress", "Failed", "Completed", or "Cancelled"; the last three are terminal), percent_complete, records_imported, uri, and error when it failed.

Raises:
Return type:

ImportModel

Examples

import_op = idx.describe_import("1")
print(import_op.status, import_op.percent_complete)

See also

  • start_import(): starts an import and returns the id these methods take.

  • list_imports(): every import on the index, when you do not have an id.

cancel_import(id)[source]

Cancel a bulk import operation by ID.

Parameters:

id (str | int) – The id start_import() returned, e.g. "1". An int is accepted and converted to a string.

Returns:

None. Poll describe_import() to see the import reach "Cancelled".

Raises:
Return type:

None

Examples

idx.cancel_import("1")

See also

  • start_import(): starts an import and returns the id these methods take.

  • list_imports(): every import on the index, when you do not have an id.

list_imports(*, limit=None, pagination_token=None)[source]

List every bulk import on this index, following pagination.

Yields ImportModel objects rather than pages, and fetches the next page as you exhaust the current one, so nothing is requested until you iterate. See Pagination.

Parameters:
  • limit (int | None) – Maximum number of imports per page, e.g. 10. Omit to let the server choose the page size.

  • pagination_token (str | None) – Token to resume from, when you are continuing a listing rather than starting one.

Yields:

ImportModel for each import operation.

Raises:

ApiError – If a page request fails part-way through the listing; the imports already yielded are still yours, the rest are not.

Return type:

Iterator[ImportModel]

Examples

for imp in idx.list_imports():
    print(imp.id, imp.status)

See also

list_imports_paginated(*, limit=None, pagination_token=None)[source]

Fetch one page of bulk imports, holding the token yourself.

list_imports() walks the pages for you; use this one when you need to persist the token between calls. See Pagination.

Parameters:
  • limit (int | None) – Maximum number of imports in this page, e.g. 10.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

Returns:

ImportList you can iterate for this page’s ImportModel objects, with pagination.next holding the token for the following page or None on the last one.

Return type:

ImportList

Examples

page = idx.list_imports_paginated(limit=10)
for imp in page:
    print(imp.id, imp.status)
next_token = page.pagination.next if page.pagination else None

See also

close()[source]

Close the connection to the index and release background resources.

Waits for any in-flight *_async submissions to finish, then closes the network connection. Call this when you are done issuing requests through this client and are not using it as a context manager.

Examples

idx = pc.index(name="articles-en", grpc=True)
idx.upsert(vectors=all_vectors, namespace="published")
idx.close()

See also

__enter__(): using the client as a context manager closes it for you, including on the way out of an exception.

Return type:

None

__enter__()[source]

Enter a context manager block, returning this client unchanged.

Examples

with pc.index(name="articles-en", grpc=True) as idx:
    idx.upsert(vectors=all_vectors, namespace="published")
Return type:

GrpcIndex

__exit__(*args)[source]

Exit the context manager block, calling close().

Parameters:

args (Any)

Return type:

None

PineconeFuture

The *_async() methods on GrpcIndex return a PineconeFuture, which works with concurrent.futures.as_completed() and concurrent.futures.wait().

class pinecone.grpc.future.PineconeFuture(underlying)[source]

Bases: Future[_T]

A handle on a GrpcIndex.*_async() call that is already in flight.

The call was handed to a background thread and the method returned immediately. Issue as many as you want, then collect them: call result() to block for one, or pass the whole batch to concurrent.futures.as_completed() or concurrent.futures.wait(), both of which this class supports. A future you never collect is not cancelled: the request still reaches the server.

This is threads, not await. Nothing here is awaitable, and the surrounding function does not need to be async. If your code is already running under asyncio, AsyncIndex is the client you want instead: its methods are coroutines, so a pending request yields to the event loop rather than parking a worker thread.

result() and exception() default to a 5 second wait, short enough that an unfinished call raises rather than hanging; pass an explicit timeout= for anything slower, or timeout=None to block until the call settles.

Examples

from pinecone import Pinecone

pc = Pinecone(api_key="your-api-key")
idx = pc.index(name="article-search", grpc=True)
future = idx.upsert_async(vectors=[("article-101", [0.012, -0.087, 0.153])])
print(future.result().upserted_count)

Issuing several at once is the reason to prefer these over the blocking methods, because the requests overlap instead of queueing:

from concurrent.futures import as_completed

futures = [
    idx.upsert_async(vectors=[("article-101", [0.012, -0.087, 0.153])]),
    idx.upsert_async(vectors=[("article-102", [0.045, 0.021, -0.064])]),
]
for future in as_completed(futures):
    print(future.result().upserted_count)

See also

AsyncIndex: the asyncio client, for code that awaits rather than joining threads. See Sync vs async clients.

Parameters:

underlying (Future[_T])

__init__(underlying)[source]

Initializes the future. Should not be called by clients.

Parameters:

underlying (Future[_T])

Return type:

None

result(timeout=5.0)[source]

Block until the call settles, then return what it returned.

Parameters:

timeout (float | None) – Maximum seconds to wait, defaulting to 5.0. Pass None to block until the call settles, however long that takes.

Returns:

Whatever the underlying GrpcIndex method would have returned had you called it directly: an UpsertResponse from upsert_async, a QueryResponse from query_async, and so on.

Raises:
  • PineconeTimeoutError – If timeout elapses first. The call is still in flight and may yet reach the server; call result() again to keep waiting.

  • Exception – Whatever the underlying GrpcIndex method raised, for example ApiError.

Return type:

_T

Examples

future = idx.upsert_async(vectors=[("article-101", [0.012, -0.087, 0.153])])
print(future.result().upserted_count)

A large batch usually needs more than the 5-second default:

future = idx.upsert_async(vectors=large_batch)
result = future.result(timeout=30.0)
exception(timeout=5.0)[source]

Block until the call settles, then return how it failed, or None.

Use this to inspect a failure without it propagating, where result() would re-raise it.

Parameters:

timeout (float | None) – Maximum seconds to wait, defaulting to 5.0. Pass None to block until the call settles.

Returns:

The exception the call raised, or None if it succeeded.

Raises:

PineconeTimeoutError – If timeout elapses before the call settles. This is the wait timing out, not the call failing.

Return type:

BaseException | None

Examples

future = idx.upsert_async(vectors=[("article-101", [0.012, -0.087, 0.153])])
error = future.exception(timeout=30.0)
if error is not None:
    print("upsert failed:", error)
cancel()[source]

Try to cancel the call before a worker thread picks it up.

Returns True only if the call had not started yet. Once it is running there is no way to recall it: you get False and the request still reaches the server, so treat a False here as “the write may land” rather than “nothing happened”.

Examples

future = idx.upsert_async(vectors=[("article-101", [0.012, -0.087, 0.153])])
if not future.cancel():
    future.result(timeout=30.0)
Return type:

bool

cancelled()[source]

Return True if the call was successfully cancelled.

Return type:

bool

done()[source]

Return True if the call has completed or was cancelled.

Return type:

bool

running()[source]

Return True if the call is currently being executed.

Return type:

bool

add_done_callback(fn)[source]

Run fn once the call settles, instead of blocking on it.

fn receives this future as its only argument, and runs on the worker thread that finished the call, so keep it short, and do not call result() on a different pending future from inside it. Adding a callback to a future that has already settled runs fn immediately, on the calling thread.

Examples

def log_result(future):
    print("upserted", future.result().upserted_count)

idx.upsert_async(
    vectors=[("article-101", [0.012, -0.087, 0.153])]
).add_done_callback(log_result)
Parameters:

fn (Callable[[...], Any])

Return type:

None