You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python卫星位置检测项目报错:TypeError:列表索引需为整数或切片而非字符串

卫星位置检测项目Python报错解决

错误信息

Traceback (most recent call last):
  File "C:\Users\soumy\OneDrive\Desktop\PySatelliteFinder\main.py", line 50, in <module>
    calculate_and_display_position(name.upper())  # Convert to uppercase for TLE lookup
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\soumy\OneDrive\Desktop\PySatelliteFinder\main.py", line 15, in calculate_and_display_position
    satellite = ts[name]
                ~~^^^^^^
TypeError: list indices must be integers or slices, not str

问题代码

import turtle
from datetime import datetime
from skyfield.api import Topos, load

# Function to calculate and display satellite position
def calculate_and_display_position(name):
    # Clear previous drawing
    screen.clear()
    
    # Load TLE data
    ts = load.tle_file('stations.txt')
    
    try:
        satellite = ts[name]
    except KeyError:
        screen.write(f"Satellite '{name}' not found.", align="center", font=("Arial", 16, "normal"))
        return

    # Get current UTC time
    current_time = datetime.utcnow()
    
    # Calculate satellite position
    topos = satellite.at(ts.utc(current_time.year, current_time.month, current_time.day,
                                  current_time.hour, current_time.minute, current_time.second))
    alt, az, _ = topos.observe(observer_location).apparent().altaz()

    # Display satellite name, position, and local time
    screen.write(f"Satellite: {name}\n"
                 f"Altitude: {alt.degrees:.2f} degrees\n"
                 f"Azimuth: {az.degrees:.2f} degrees\n"
                 f"Local Time: {current_time}", align="left", font=("Arial", 16, "normal"))

# Create a Turtle screen
screen = turtle.Screen()
screen.bgpic("world_map.gif")  # You'll need to provide a world map image

# Create an observer location
observer_location = Topos(latitude_degrees=23.247921, longitude_degrees=87.871365)

# Initialize the Turtle
satellite_turtle = turtle.Turtle()
satellite_turtle.penup()
satellite_turtle.goto(0, 200)
satellite_turtle.hideturtle()

# Input box for satellite name
name = screen.textinput("Enter Satellite Name", "Enter the satellite name:")
if name:
    calculate_and_display_position(name.upper())  # Convert to uppercase for TLE lookup

# Listen for clicks to change satellite
screen.onclick(lambda x, y: calculate_and_display_position(screen.textinput("Enter Satellite Name", "Enter the satellite name:").upper()))

# Close the window when clicked
screen.exitonclick()

问题分析

  1. 变量名冲突:代码中把load.tle_file()返回的卫星列表命名为ts,但Skyfield中ts通常指代时间尺度对象(load.timescale()),后续调用ts.utc()会引发逻辑错误,同时导致变量混淆。
  2. 列表无法通过字符串索引:load.tle_file()返回的是卫星对象的列表,只能用整数索引,无法直接通过卫星名称(字符串)获取对应对象,这是触发当前报错的直接原因。

解决方案

  • 分离变量名:将TLE加载的卫星列表命名为satellites_list,单独加载时间尺度对象为ts,避免命名冲突。
  • 转换卫星列表为字典:用字典推导式将卫星列表转为以卫星名称大写为键的字典,匹配输入的大写格式,方便通过名称快速索引。
  • 修正时间计算逻辑:使用正确的时间尺度对象ts生成Skyfield可识别的时间格式。
  • 增加卫星标记逻辑:将卫星经纬度转换为海龟屏幕坐标,在地图上用红色标记卫星位置并显示名称。

修正后完整代码

import turtle
from datetime import datetime
from skyfield.api import Topos, load

# 预加载时间尺度和TLE数据,避免重复加载提升效率
ts = load.timescale()
satellites_list = load.tle_file('stations.txt')
# 转换为大写名称为键的字典,匹配输入格式
satellites_dict = {sat.name.upper(): sat for sat in satellites_list}

# 地图坐标转换参数(根据你的世界地图实际尺寸调整)
MAP_WIDTH = 800
MAP_HEIGHT = 600
LON_SCALE = MAP_WIDTH / 360
LAT_SCALE = MAP_HEIGHT / 180

def calculate_and_display_position(name):
    # 清空之前的绘制内容
    screen.clear()
    satellite_turtle.clear()
    satellite_turtle.penup()
    satellite_turtle.hideturtle()

    try:
        satellite = satellites_dict[name]
    except KeyError:
        screen.write(f"Satellite '{name}' not found.", align="center", font=("Arial", 16, "normal"))
        return

    # 获取当前UTC时间并转换为Skyfield时间格式
    current_time = datetime.utcnow()
    skyfield_time = ts.utc(current_time.year, current_time.month, current_time.day,
                          current_time.hour, current_time.minute, current_time.second)
    
    # 计算卫星的地面投影位置
    geocentric = satellite.at(skyfield_time)
    subpoint = geocentric.subpoint()
    lat = subpoint.latitude.degrees
    lon = subpoint.longitude.degrees

    # 计算卫星相对于观测者的高度和方位角
    alt, az, _ = geocentric.observe(observer_location).apparent().altaz()

    # 将经纬度转换为海龟屏幕坐标
    x = lon * LON_SCALE
    y = lat * LAT_SCALE

    # 用红色标记卫星位置并显示名称
    satellite_turtle.goto(x, y)
    satellite_turtle.dot(10, 'red')
    satellite_turtle.write(name, align="center", font=("Arial", 12, "bold"))

    # 显示卫星详细信息
    screen.write(f"Satellite: {name}\n"
                 f"Latitude: {lat:.2f}°\n"
                 f"Longitude: {lon:.2f}°\n"
                 f"Altitude: {alt.degrees:.2f}°\n"
                 f"Azimuth: {az.degrees:.2f}°\n"
                 f"UTC Time: {current_time}", align="left", font=("Arial", 16, "normal"))

# 创建海龟绘图窗口
screen = turtle.Screen()
screen.setup(width=MAP_WIDTH, height=MAP_HEIGHT)
screen.bgpic("world_map.gif")  # 确保世界地图图片路径正确

# 设置观测者位置
observer_location = Topos(latitude_degrees=23.247921, longitude_degrees=87.871365)

# 初始化卫星标记海龟
satellite_turtle = turtle.Turtle()
satellite_turtle.penup()
satellite_turtle.hideturtle()

# 弹出卫星名称输入框
name = screen.textinput("Enter Satellite Name", "Enter the satellite name:")
if name:
    calculate_and_display_position(name.upper())

# 点击窗口触发新的卫星查询
def on_click(x, y):
    new_name = screen.textinput("Enter Satellite Name", "Enter the satellite name:")
    if new_name:
        calculate_and_display_position(new_name.upper())

screen.onclick(on_click)

# 点击窗口关闭程序
screen.exitonclick()

说明

  • 预加载TLE数据和时间尺度,避免每次调用函数重复加载,提升运行效率。
  • 地图坐标转换参数可根据你的世界地图实际尺寸调整,确保卫星位置标记准确。
  • 实现了红色标记卫星位置、显示卫星名称及详细参数的功能。

内容的提问来源于stack exchange,提问作者epubby sudsou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:09:53