{"id":7644,"library":"pyvo","title":"PyVO","description":"PyVO is an Astropy affiliated package that provides a Python interface to access data and services from the Virtual Observatory (VO). It allows users to query astronomical catalogs, image archives, and spectral data through standard VO protocols like TAP, SIA, and SSA. The current version is 1.8.1, and it maintains an active release cadence with regular updates and bug fixes.","status":"active","version":"1.8.1","language":"en","source_language":"en","source_url":"https://github.com/astropy/pyvo","tags":["astronomy","virtual observatory","VO","data access","astropy","DAL","TAP","SIA","SSA"],"install":[{"cmd":"pip install pyvo","lang":"bash","label":"Install PyVO"}],"dependencies":[{"reason":"PyVO is built on Astropy's core functionalities, especially for data handling and astronomical units/coordinates.","package":"astropy"},{"reason":"Used internally for HTTP requests to VO services. While often a transitive dependency, issues can arise if not correctly installed.","package":"requests"}],"imports":[{"symbol":"pyvo","correct":"import pyvo"},{"note":"Services were moved to the `pyvo.dal` submodule in earlier versions (pre-1.0) and this old path may persist in older examples.","wrong":"from pyvo.services import TAPService","symbol":"TAPService","correct":"from pyvo.dal import TAPService"},{"note":"While `from pyvo import registry` works, `import pyvo.registry` is more explicit and common in examples for sub-modules.","wrong":"from pyvo import registry","symbol":"registry","correct":"import pyvo.registry"}],"quickstart":{"code":"import pyvo\nimport os\n\n# 1. Search the VO registry for services\n# Example: Find services related to galaxies and spectroscopy\nprint(\"Searching the VO registry...\")\nresults = pyvo.registry.search(keywords=['galaxy', 'spectroscopy'])\nprint(f\"Found {len(results)} services matching 'galaxy' and 'spectroscopy'.\")\n\n# 2. Access a TAP service (Table Access Protocol)\n# For a stable quickstart, we'll use a widely known public TAP service.\n# Note: Service availability can change. This is an example.\ntap_service_url = os.environ.get('PYVO_TAP_SERVICE_URL', 'https://tap.voservices.net/tap')\ntap_service = pyvo.dal.TAPService(tap_service_url)\nprint(f\"\\nAttempting to connect to TAP service: {tap_service.url}\")\n\n# 3. Execute an ADQL (Astronomical Data Query Language) query\n# Example: Query the ivoa.ObsCore table for Gaia data\nquery = \"SELECT TOP 5 ra, dec, dataproduct_type FROM ivoa.ObsCore WHERE obs_collection LIKE '%Gaia%'\"\ntry:\n    tap_results = tap_service.search(query)\n    print(f\"\\nTAP query returned {len(tap_results)} results.\")\n    # Results are returned as an Astropy Table object (pyvo.dal.TableSet)\n    print(\"\\nFirst 5 results (Astropy Table):\")\n    print(tap_results.to_table())\nexcept Exception as e:\n    print(f\"\\nError during TAP query: {e}\")\n    print(\"The TAP service might be temporarily unavailable or the query invalid.\")\n","lang":"python","description":"This quickstart demonstrates how to search the Virtual Observatory registry for services and then execute a simple ADQL query against a public TAP (Table Access Protocol) service using PyVO. Results are returned as Astropy Table objects, integrating well with the broader Astropy ecosystem."},"warnings":[{"fix":"Review your code for positional arguments, especially for optional parameters, and explicitly pass them as keyword arguments (e.g., `func(arg1, arg2=value)` instead of `func(arg1, value)`).","message":"Starting with PyVO v1.6, many optional arguments to functions and methods were changed to be keyword-only. This means calling them positionally will raise a `TypeError`.","severity":"breaking","affected_versions":">=1.6"},{"fix":"Upgrade to PyVO >= 1.8.1 to ensure proper timeout handling for asynchronous TAP jobs. If upgrading is not possible, implement external timeout mechanisms or carefully monitor job status.","message":"Asynchronous TAP job handling in versions prior to 1.8.1 might not correctly implement or respect timeout parameters for `run_async` methods, potentially leading to jobs hanging indefinitely.","severity":"gotcha","affected_versions":"<1.8.1"},{"fix":"Upgrade to PyVO >= 1.8.1 to leverage `DALRateLimitError` for more robust handling of rate limits, including automatic retry logic where available. For older versions, implement custom retry logic for HTTP 429 errors.","message":"Error handling for HTTP 429 (Too Many Requests) responses was improved in v1.8.1 with the introduction of `DALRateLimitError`. Older versions might raise generic HTTP errors without explicit retry information.","severity":"gotcha","affected_versions":"<1.8.1"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Install Astropy: `pip install astropy`.","cause":"The core `astropy` library, a fundamental dependency for PyVO, is not installed in your environment.","error":"ModuleNotFoundError: No module named 'astropy'"},{"fix":"Check the specific HTTP error code for details. Verify the service URL, ensure your query is valid, and check the service's status if possible. Network connectivity issues can also cause this.","cause":"The remote Virtual Observatory service is inaccessible, unavailable, or returned an error for your request (e.g., invalid query, authentication issue, server-side problem).","error":"pyvo.exceptions.DALServiceError: HTTP Error 4xx: Client Error or HTTP Error 5xx: Server Error"},{"fix":"Identify the method in question and change its call signature to use keyword arguments for all optional parameters. For example, change `method(param1, value_for_optional)` to `method(param1, optional_param=value_for_optional)`.","cause":"You are passing optional arguments positionally to a PyVO function or method that now expects them as keyword arguments due to API changes in v1.6.","error":"TypeError: some_method() takes 1 positional argument but N were given"}]}