> ## Documentation Index
> Fetch the complete documentation index at: https://dune-tables-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Execution & Results

In this quickstart, we will walk through how to fetch Dune data in Python.

### Prerequisites

* Python environment set up (check out [Anaconda Navigator](https://docs.continuum.io/free/navigator/) if you want somewhere to start.)
* Have a Dune API key (to obtain one [follow the steps here](../overview/authentication#generate-an-api-key))

<Tip>
  Save your Dune API key in a .env file.

  ```
  DUNE_API_KEY=<paste your API key here>
  ```
</Tip>

### Step 1: Prepare your Dune query

Have a Dune query you'd like to pull data from. Here, we'll use [this query](https://dune.com/queries/3373921/5660178) to get the DAI token balance for vitalik.eth.

### Step 2: Install Dune Python SDK

Ensure the [Dune Python SDK](https://pypi.org/project/dune-client/) is installed in your environment. You can install it using pip:

```
pip install dune-client
```

### Step 3: Get data from Dune query

#### Import packages and set up a Dune Python client

```python
import dotenv, os
from dune_client.types import QueryParameter
from dune_client.client import DuneClient
from dune_client.query import QueryBase

# change the current working directory where .env file lives
os.chdir("/Users/abc/project")
# load .env file
dotenv.load_dotenv(".env")
# setup Dune Python client
dune = DuneClient.from_env()
```

<Tip>
  To avoid request timeout, you can increase the request timeout setting to be higher than the default 10 seconds in the same .env file we saved the API key information.

  ```
  DUNE_API_KEY=<paste your API key here>
  DUNE_API_REQUEST_TIMEOUT=120
  ```
</Tip>

#### Get query result

You can choose to either get the latest query result without triggering an execution or to trigger an execution and get the result to ensure freshest data.

<Tabs>
  <Tab title="Get latest result without execution">
    ```python
      query_result = dune.get_latest_result(3373921) # get latest result in json format
      # query_result = dune.get_latest_result_dataframe(3373921) # get latest result in Pandas dataframe format
    ```
  </Tab>

  <Tab title="Query a query">
    ```python
    query = QueryBase(
        query_id=3373921,

        # uncomment and change the parameter values if needed
        # params=[
        #     QueryParameter.text_type(name="contract", value="0x6B175474E89094C44Da98b954EedeAC495271d0F"), # default is DAI
        #     QueryParameter.text_type(name="owner", value="owner"), # default using vitalik.eth's wallet 
        # ],
    )

    query_result = dune.run_query_dataframe(
      query=query
      # , ping_frequency = 10 # uncomment to change the seconds between checking execution status, default is 1 second
      # , performance="large" # uncomment to run query on large engine, default is medium
      # , batch_size = 5_000 # uncomment to change the maximum number of rows to retrieve per batch of results, default is 32_000
    ) 

    # Note: to get the result in csv format, call run_query_csv(); for json format, call run_query().
    ```
  </Tab>
</Tabs>

<Note>
  * To paginate query results, please visit the [pagination page](../executions/pagination) to get more info.
  * If you are using the [Python SDK](https://github.com/duneanalytics/dune-client/tree/main):
    * For [higher level functions](https://github.com/duneanalytics/dune-client/blob/main/dune_client/api/extensions.py) like `run_query()`, pagination is handled for you automatically behind the scene, so you will get the entire dataset as the returned result. You can pass in parameter `batch_size` to define the maximum number of rows per batch or pagination call.
    * For [lower level functions](https://github.com/duneanalytics/dune-client/blob/main/dune_client/api/execution.py) like `get_execution_results()`, you can pass in pagination parameters `limit` and `offset` directly, as instructed [here](../executions/pagination#pagination-parameters).
</Note>

<Accordion title="Putting it all together">
  ```python
  import dotenv, os
  from dune_client.types import QueryParameter
  from dune_client.client import DuneClient
  from dune_client.query import QueryBase

  # change the current working directory where .env file lives
  os.chdir("/Users/abc/project")
  # load .env file
  dotenv.load_dotenv(".env")
  # setup Dune Python client
  dune = DuneClient.from_env()

  """ get the latest executed result without triggering a new execution """
  query_result = dune.get_latest_result(3373921) # get latest result in json format
  # query_result = dune.get_latest_result_dataframe(3373921) # get latest result in Pandas dataframe format


  """  query the query (execute and get latest result) """
  query = QueryBase(
      query_id=3373921,

      # uncomment and change the parameter values if needed
      # params=[
      #     QueryParameter.text_type(name="contract", value="0x6B175474E89094C44Da98b954EedeAC495271d0F"), # default is DAI
      #     QueryParameter.text_type(name="owner", value="owner"), # default using vitalik.eth's wallet 
      # ],
  )

  query_result = dune.run_query_dataframe(
    query=query
    # , ping_frequency = 10 # uncomment to change the seconds between checking execution status, default is 1 second
    # , performance="large" # uncomment to run query on large engine, default is medium
    # , batch_size = 5_000 # uncomment to change the maximum number of rows to retrieve per batch of results, default is 32_000
  ) 

  # Note: to get the result in csv format, call run_query_csv(); for json format, call run_query().
  ```
</Accordion>
