[Python] Python/Tweepy script posts blank image from OpenWeatherMap Tile API in twitter

Discussão em 'Python' iniciado por Stack, Junho 7, 2025.

  1. Stack

    Stack Membro Participativo

    I have a Python script that fetches weather data and a corresponding weather map tile from OpenWeatherMap, then posts them to Twitter using Tweepy.

    The script successfully fetches text data and posts the tweet. It also creates an image file for the map. However, the image that gets posted to Twitter is always blank or empty.

    The actual Problem:

    When the script runs, the get_weather_map_tile function downloads and saves a .png file. No errors are thrown during the download or the Tweepy upload process. But the final post on Twitter contains a blank white or black square instead of a map.

    When I inspect the saved weather_map.png file on the server just before it's uploaded, I've noticed it sometimes contains text, not an image. For example, it might contain an error message like: {"cod":401, "message": "Invalid API key. ..."} or {"cod": 404, "message": "tile not found"}.

    My senior looked at the code and he himself told, "I don't know".

    My Code:

    Here are the relevant functions from my script:

    import tweepy
    import requests
    import os
    import math

    # This function fetches the map tile
    def get_weather_map_tile(lat, lon, weather_api_key, zoom=10, layer="clouds_new", filename="weather_map.png"):
    """Fetches a weather map tile from OpenWeatherMap and saves it."""
    try:
    # Calculate tile coordinates from lat/lon
    lon_rad = math.radians(lon)
    lat_rad = math.radians(lat)
    n = 2.0 ** zoom
    x_tile = int((lon + 180.0) / 360.0 * n)
    y_tile = int((1.0 - math.asinh(math.tan(lat_rad)) / math.pi) / 2.0 * n)

    map_url = f"https://tile.openweathermap.org/map/{layer}/{zoom}/{x_tile}/{y_tile}.png?appid={weather_api_key}"
    print(f"Fetching weather map from: {map_url}")

    response = requests.get(map_url, stream=True)
    response.raise_for_status() # This catches 4xx/5xx server errors

    # Check if the response is actually an image before saving
    if 'image/png' in response.headers.get('Content-Type', '').lower():
    with open(filename, 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
    f.write(chunk)
    print(f"Weather map tile saved to {filename}")
    return filename
    else:
    # PROBLEM: What if the API returns a 200 OK but with an error in the body?
    print(f"Failed to get a PNG image. Content-Type: {response.headers.get('Content-Type')}")
    print(f"Response Body: {response.text}") # This is where I see the JSON error
    return None

    except requests.exceptions.HTTPError as http_err:
    print(f"HTTP error fetching weather map: {http_err}")
    if 'response' in locals() and response.content:
    print(f"Response content: {response.text}")
    return None
    except Exception as e:
    print(f"An unexpected error occurred in get_weather_map_tile: {e}")
    return None

    # This function handles the tweet posting
    def tweet_post(tweet_text, media_path=None):
    # Assume bot_api_client = tweepy.Client(...) is initialized globally
    try:
    media_id_str = None
    if media_path and os.path.exists(media_path):
    print(f"Uploading media: {media_path}")
    media = bot_api_client.media_upload(filename=media_path)
    media_id_str = media.media_id_string
    print(f"Media uploaded successfully. Media ID: {media_id_str}")

    if media_id_str:
    bot_api_client.create_tweet(text=tweet_text, media_ids=[media_id_str])
    else:
    # Fallback to text-only if media fails
    bot_api_client.create_tweet(text=tweet_text)
    print("Tweet posted successfully!")

    except Exception as e:
    print(f"An error occurred during tweeting: {e}")
    finally:
    # Clean up the media file
    if media_path and os.path.exists(media_path):
    os.remove(media_path)

    # --- How the functions are called ---
    # This is a simplified version of my main logic
    def main_job():
    city_lat = 17.44
    city_lon = 78.34
    my_api_key = "YOUR_WEATHER_API_KEY" # My key is valid for text data
    tweet_content = "Here is the weather for Gachibowli..."

    # Fetch the map
    map_image_path = get_weather_map_tile(city_lat, city_lon, my_api_key)

    # Post the tweet
    if map_image_path:
    tweet_post(tweet_content, media_path=map_image_path)
    else:
    print("Skipping tweet post because map image could not be generated.")

    # Example global client setup
    # bot_api_client = tweepy.Client(..., wait_on_rate_limit=True)


    Verified API Keys: My OpenWeatherMap API key works perfectly for fetching weather data from other endpoints (/data/2.5/weather).

    Checked the URLs: I have manually copied the generated map_url into my browser. Sometimes it shows a map, but other times (especially if I refresh quickly) it shows a 404 Not Found or 401 Unauthorized error page,

    checked the File: As mentioned, the downloaded .png file often contains a JSON error message, not image data. My current code does not robustly handle this case, leading to the blank image upload.

    Tried to do Error Handling: response.raise_for_status() correctly catches clear HTTP errors like 401 or 404, but it doesn't seem to catch cases where the API returns a 200 OK status with an error message in the JSON body

    Continue reading...

Compartilhe esta Página