An asynchronous Python library for working with GeoNames data using a database backend.
- Asynchronous database operations for GeoNames data
- Easy setup and configuration
- Efficient geolocation queries
- Customizable data storage location
pip install python-geonamesHere's a quick example of how to use the main features of python-geonames:
importasynciofrompathlibimportPathfromloguruimportloggerfromgeonames.databaseimportget_geolocation, setup_databasefromgeonames.configimportConfigasGeoNamesConfigasyncdefmain():
# Configure the libraryconfig=GeoNamesConfig()
config.SAVE_DIR=Path(__file__).parent/"geonames_data"# Set up the databaseengine=awaitsetup_database(config)
# Perform a geolocation queryresults=awaitget_geolocation(engine, "US", "39046")
logger.info(f"Geolocation results: {results}")
if__name__=="__main__":
asyncio.run(main())You can customize the configuration by modifying the GeoNamesConfig object:
fromgeonames.configimportConfigasGeoNamesConfigconfig=GeoNamesConfig()
config.SAVE_DIR=Path("/custom/path/to/geonames_data")
config.DATABASE_URL="sqlite:///custom_database.db"# Add other configuration options as neededimportasynciofromgeonames.databaseimportget_geolocation, setup_databasefromgeonames.configimportConfigasGeoNamesConfigasyncdefperform_multiple_queries(engine):
queries= [
("US", "39046"),
("GB", "L1"),
("DE", "10115"),
]
results=awaitasyncio.gather(*[get_geolocation(engine, country, postal_code) forcountry, postal_codeinqueries])
forquery, resultinzip(queries, results):
print(f"Results for {query[0]}{query[1]}: {result}")
asyncdefmain():
config=GeoNamesConfig()
engine=awaitsetup_database(config)
awaitperform_multiple_queries(engine)
if__name__=="__main__":
asyncio.run(main())It's important to handle potential errors when working with the database:
importasynciofromloguruimportloggerfromsqlalchemy.excimportSQLAlchemyErrorfromgeonames.databaseimportget_geolocation, setup_databasefromgeonames.configimportConfigasGeoNamesConfigasyncdefsafe_get_geolocation(engine, country, postal_code):
try:
returnawaitget_geolocation(engine, country, postal_code)
exceptSQLAlchemyErrorase:
logger.error(f"Database error occurred: {e}")
returnNoneasyncdefmain():
config=GeoNamesConfig()
try:
engine=awaitsetup_database(config)
result=awaitsafe_get_geolocation(engine, "US", "39046")
ifresult:
logger.info(f"Geolocation results: {result}")
else:
logger.warning("No results found or an error occurred.")
exceptExceptionase:
logger.error(f"An unexpected error occurred: {e}")
if__name__=="__main__":
asyncio.run(main())For more detailed usage instructions, please refer to the documentation.
This project uses GitHub Actions for continuous integration. The workflow runs tests on Python 3.10 and 3.11, and reports code coverage.
To set up the GitHub Action:
Copy the contents of the
.github/workflows/python-tests.ymlfile from this repository to your own repository.Ensure your repository has the necessary secrets set up:
GITHUB_TOKEN: This is automatically provided by GitHub Actions.
Make sure your
pyproject.tomlfile includes all necessary dependencies, including test and development dependencies.Sign up for a Codecov account and add your repository.
The GitHub Action will now run automatically on every push to the
mainbranch and every pull request targeting themainbranch.
You can view the status of the tests and coverage in the shields at the top of this README.
This project uses Poetry for dependency management. To set up the development environment:
Install Poetry if you haven't already:
curl -sSL https://install.python-poetry.org | python3 -Clone the repository:
git clone https://github.com/Aareon/python-geonames.git cd python-geonamesInstall the project dependencies:
poetry install --with test,develop
Activate the virtual environment:
poetry shell
To run the tests:
pytestTo run the tests with coverage:
pytest --cov=geonames tests/To run type checking with mypy:
mypy geonamesThis project uses black for code formatting and isort for import sorting. To format your code:
black .
isort .To run the linter:
ruff check .Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the terms of the MIT license. See LICENSE for more details.