Cloud Managed
PostgreSQL

High performance. Open source. Favorite SQL — in the clouds.
Cloud Managed PostgreSQL
Feature-rich
PostgreSQL is a database with a tremendous amount of features and extensions. You can code for it in SQL, JS, C and C++, Java, Python, PHP, Lua and Ruby.
Object-relational
This database takes advantage of an object-oriented approach. More features — for convenient work and productivity.
Large Data Volumes
With PostgreSQL you can work with data of any size. One table alone can take up to 32 TB.
With a Trusted Hoster
And all of this — on top notch hardware on a pay-as-you-go model. Hostman's support and user-friendly control panel are already waiting for you.

Pricing

PostgreSQL
New York
1 x 3 GHz CPU
CPU
1 x 3 GHz
1 GB RAM
RAM
1 GB
20 GB NVMe
NVMe
20 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$4
 /mo
1 x 3 GHz CPU
CPU
1 x 3 GHz
2 GB RAM
RAM
2 GB
60 GB NVMe
NVMe
60 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$9
 /mo
2 x 3 GHz CPU
CPU
2 x 3 GHz
4 GB RAM
RAM
4 GB
80 GB NVMe
NVMe
80 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$18
 /mo
4 x 3 GHz CPU
CPU
4 x 3 GHz
8 GB RAM
RAM
8 GB
160 GB NVMe
NVMe
160 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$36
 /mo
6 x 3 GHz CPU
CPU
6 x 3 GHz
16 GB RAM
RAM
16 GB
320 GB NVMe
NVMe
320 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$72
 /mo
8 x 3 GHz CPU
CPU
8 x 3 GHz
32 GB RAM
RAM
32 GB
640 GB NVMe
NVMe
640 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$114
 /mo
16 x 3 GHz CPU
CPU
16 x 3 GHz
64 GB RAM
RAM
64 GB
1280 GB NVMe
NVMe
1280 GB
200 Mbps Bandwidth
Bandwidth
200 Mbps
$288
 /mo
Anup k.
Associate Cloud Engineer
5.0 out of 5

"Hostman Comprehensive Review of Simplicity and Potential"

It been few years that I have been working on Cloud and most of the cloud service...
Mansur H.
Security Researcher
5.0 out of 5

"A perfect fit for everything cloud services!"

Hostman's seemless integration, user-friendly interface and its robust features (backups, etc) makes it much easier...
Adedeji E.
DevOps Engineer
5.0 out of 5

"Superb User Experience"

For me, Hostman is exceptional because of it's flexibility and user-friendliness. The platform's ability to offer dedicated computing resources acr...
Yudhistira H.
Mid-Market(51-1000 emp.)
5.0 out of 5

"Streamlined Cloud Excellence!"

What I like best about Hostman is their exceptional speed of deployment, scalability, and robust security features. Their...
Mohammad Waqas S.
Biotechnologist and programmer
5.0 out of 5

"Seamless and easy to use Hosting Solution for Web Applications"

From the moment I signed up, the process has been seamless and straightforward...
Mohana R.
Senior Software Engineer
5.0 out of 5

"Availing Different DB Engine Services Provided by Hostman is Convenient for my Organization usecases"

Hostman manages the cloud operations...
Faizan A.
5.0 out of 5

"Hostman is a great fit for me"

Hostman is a great fit for me. What do you like best about Hostman? It was very easy to deploy my application and create database, I didn't have
Adam M.
5.0 out of 5

"Perfect website"

This website is extremely user friendly and easy to use. I had no problems so didn't have to contact customer support. Really good website and would recommend to others.
Anup K.
4.0 out of 5

"Simplifying Cloud Deployment with Strengths and Areas for Growth"

What I like best about Hostman is its unwavering commitment to simplicity...
Naila J.
5.0 out of 5

"Streamlined Deployment with Room for Improvement"

Hostman impresses with its user-friendly interface and seamless deployment process, simplifying web application hosting...

Trusted by 500+ companies and developers worldwide

One panel to rule them all

Easily control your database, pricing plan, and additional services
through the intuitive Hostman management console.
Easy set up and management
Ready-to-deploy cloud database solutions come pre-configured. Choose your setup, launch your database, and begin managing your data with ease.
Saves time and resources
Forget about configuring hardware and software or manual database management—our service has it all covered for you.
Security
Deploy databases on an isolated network to maintain private access solely through your own infrastructure.
Hostman management console, statistics for an hour

The high-performance cloud
DBMS — for any solution.
For your solutions!

Alternative databases — for all your needs

MySQL

The most popular relational database management system from Oracle. Developed under an open-source model.

PostgreSQL

An object-relational database management system. Supported by most UNIX platforms.

Redis

A high-performance database that operates on a 'key-value model'. Often used for caching.

MongoDB

A classic database management system oriented towards document storage and supporting JSON queries.

OpenSearch

A system of search and analytics resources for monitoring applications and event logs.

ClickHouse

A columnar analytical database. Supports queries to a large array of structured data in real-time mode.

Kafka

An open-source messaging system. Known for its high speed and low latency.

RabbitMQ

A messaging system based on the AMQP standard.

Code locally, launch worldwide

Our servers, certified with ISO/IEC 27001, are located in Tier 3 data
centers across the US, Europe, and Asia.
Hostmans' Locations
🇺🇸 San Francisco
🇺🇸 San Jose
🇺🇸 Texas
🇺🇸 New York
🇳🇱 Amsterdam
🇳🇬 Lagos
🇩🇪 Frankfurt
🇵🇱 Gdansk
🇦🇪 Dubai
🇸🇬 Singapore

Latest News

Debian

How to Install MySQL on Debian

Installing MySQL on Debian effectively creates a robust and flexible database (DB) infrastructure that accommodates a wide range of applications as well as services. It is renowned for its scalability, dependability, and durability. By setting it, individuals experience the operations in an efficient manner and enhance the overall efficiency of DB infrastructure. This combination is especially beneficial for administrators, DB analysts, and industries that demand a dependable database solution for dealing with huge data. Additionally, MySQL's comprehensive guide and supporters help make it simpler to troubleshoot problems and enhance operations.  In this guide, we will demonstrate the thorough procedure for installing and configuring MySQL on Debian. How to Install MySQL on Debian The default repositories do not contain the MySQL database server package on Debian. To install it on a  Linux system follow the below instructions. We will download the recent version of the MySQL. Step 1: Download MySQL Package Let us obtain the MySQL repository information package, which is in the .deb format: wget https://dev.mysql.com/get/mysql-apt-config_0.8.30-1_all.deb Note: To authenticate the most updated release, go to the MySQL repository webpage. Step 2: MySQL Configuration Package Installation Then, employ the .deb file for initializing the installation via dpkg: sudo dpkg -i mysql-apt-config_0.8.30-1_all.deb Respond to the prompt. For instance, pick MySQL Server & Cluster and hit Enter for starting configurations: For picking a version such as (mysql-8.4-lts), scroll downward and hit OK for the next step: Step 3: Refresh the System Now, update the server's package indexes to implement the updated MySQL info: sudo apt update Step 4: MySQL Installation Debian's default manager makes sure to install MySQL in an easier manner. Installing the package with this command: sudo apt install mysql-server -y You will see the interface for setting the root account. Input a stronger password to secure the database. In the end, hit the Ok button: Check the version on the server via the --version utility: mysql --version Step 5: Managing the Services Now, you can enable the MySQL service to initialize automatically at boot time: sudo systemctl enable mysql Activate the service via the systemctl utility: sudo systemctl start mysql Check if the system service is operational by viewing its status: sudo systemctl status mysql Step 6: MySQL Secure Installation The key or password that the individual created at the initialising procedure is currently protecting the root DB user on the server. MySQL also includes other insecure defaults, such as remote access to test databases and the root database user on the server.  It is vital to secure the MySQL installation after it has been completed as well as disable all unsafe default settings. There is a security script that can assist us in this procedure. Run the script: sudo mysql_secure_installation To activate the VALIDATE PASSWORD component and guarantee stringent password procedures, type Y and hit Enter. Next, you will need to configure several security settings: Set the Root Password: Select a strong password and make sure that it is correct. Configure the password policy for the DB server. For instance, type 2 to permit only the strong passwords on the server and hit Enter. When required to modify the root password, input N; alternatively, input Y to modify the password. Eliminate Anonymous Users: It is advised to eliminate the accessibility of anonymous users. For this, input Y and Enter when prompted. Prevent Accessibility of Remote Root: It is a better practice to avoid remote root login for multiple security concerns. To prevent the root user from having a remote access, input Y and hit Enter. Delete the Test DB: For enhancing security, the test database, which is utilized for testing, can be deleted. To do so, input Y and hit Enter. Refreshing Privilege Tables: It guarantees that all modifications are implemented instantly. To implement the configuration and edit the privileges table, hit Enter. Step 7: Access MySQL Utilizing the mysql client utility, MySQL establishes the connection and provides access to the database server console.  Now, access the shell interface and run general statements on the DB server. Let’s input the root and the password created at the time of the safe installation procedure: sudo mysql -u root -p Step 8: Basic MySQL Operations The creation of a DB and a new user for your applications rather than utilizing the root is a better practice. To accomplish the task, employ the given instructions: Create a Database: First, create a database. For instance, hostmandb is created via the below command: CREATE DATABASE hostmandb; Display All Databases: List all databases to make sure hostmandb is created: SHOW DATABASES; Create of a New User: Create a user and assign a strong password. In our example, we set Qwer@1234 as a password for the user  minhal. Replace these values with your data. CREATE USER 'minhal'@'localhost' IDENTIFIED BY 'Qwer@1234'; Give Permissions to the User: Give complete access to the hostmandb to the new user: GRANT ALL PRIVILEGES ON hostmandb.* TO 'minhal'@'localhost'; Flush Privileges: To implement the modifications, refresh the table: FLUSH PRIVILEGES; Exit the Shell: For closing the interface, utilize the EXIT statement: EXIT; Access MySQL Console as the Particular User For the purpose of testing hostmandb access, log in to MySQL as the new user, in our case minhal. sudo mysql -u minhal -p It accesses the console after entering the minhal user password when prompted: For verification, display all DBs and confirm that the hostmandb is available: SHOW DATABASES; Step 9: Configuration for Remote Access Setting up the server for supporting remote accessibility is necessary if an individual is required to access MySQL remotely. Follow these steps: Access the mysql.cnf file and modify the particular file for MySQL: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf Look for the line with the bind-address and change it to: bind-address = 0.0.0.0 Reload the MySQL service: sudo systemctl restart mysql Permit the user to have remote access: sudo mysql -u root -p GRANT ALL PRIVILEGES ON hostmandb.* TO 'minhal'@'localhost';FLUSH PRIVILEGES;EXIT; Step 10: Firewall Configuration If you have a firewall activated, you need to open the MySQL port 3306 to traffic. Set up the firewall following the below steps: Allow traffic through MySQL: sudo ufw allow mysql Now, activate the UFW on the system: sudo ufw enable Reload the firewall: sudo ufw reload Step 11: Restore and Backup Maintaining regular backups is crucial to avoiding data loss. The mysqldump utility is provided by MySQL for backup creation. To achieve this, consider these instructions: Backup a Single Database: This command employs mysqldump to create the backup of the hostmandb as a hostmandb_backup.sql file: sudo mysqldump -u root -p hostmandb> hostmandb_backup.sql Backup All Databases: For creating a backup of all databases as a file named all_databases_backup.sql with root privileges, utilize mysqldump: sudo mysqldump -u root -p --all-databases > all_databases_backup.sql Restore a Particular Database: Now, restore the hostmandb from the backup file hostmandb_backup.sql: sudo mysql -u root -p hostmandb < hostmandb_backup.sql Step 12: Optimize MySQL Operations (Optional) Depending on the workload and server resources, you can adjust settings to guarantee peak performance. These instructions will help you maximize MySQL's speed: Adjust InnoDB Buffer Pool Size: Caches for data and indexes are kept in the InnoDB buffer pool. Expanding its size can enhance its functionality. Edit the MySQL configuration file: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf The below line should be added or changed: innodb_buffer_pool_size = 1G Its size should be adjusted according to the amount of memory on the server. Enable Query Cache: The query cache stores the outcome of SELECT queries. Enabling it can enhance operations for repetitive queries. Modify the .cnf file: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf Add or edit the below lines: query_cache_type = 1query_cache_size = 64M Optimize Table Structure: Frequently optimize your customers table in hostmandb to recover wasted space and boost efficiency: USE hostmandb;OPTIMIZE TABLE customers; Analyze Operations: DB operations can be tracked and analyzed with tools like MySQL Workbench and mysqltuner. Using the command below, install mysqltuner: sudo apt install mysqltuner Run mysqltuner to get performance recommendations: sudo mysqltuner Conclusion Installing a MySQL environment is important in today's digital world. By following this instruction, you'll be able to safely install and connect to your MySQL database. This strategy not only increases security but also improves remote database maintenance efficiency. It helps to prevent breaches and ensures the confidentiality of your data. This article has given thorough instructions for the installation of MySQL's database environment on Debian. It is suggested that MySQL servers should be regularly monitored and optimized to guarantee optimum performance and dependability. In addition, Hostman offers pre-configured and ready-to-use cloud databases, including cloud MySQL. 
14 January 2025 · 8 min to read
Apache

How To Install the Apache Web Server on Ubuntu 22.04

Apache stands out as one of the most recognized and broadly utilized open-source web platforms across the globe. It is renowned for its dependability, adaptability, and profound usage. Its modular design, rich feature set, and compatibility with diverse operating systems make it a preferred choice for developers and IT professionals. For both novice and seasoned administrators, knowing how to do the installation and configuration of Apache properly is crucial, whether they are managing a sophisticated online infrastructure or setting up a simple website. With the help of this tutorial, users will build a reliable foundation for their web hosting requirements by installing Apache on Ubuntu 22.04, setting it up for maximum performance, and confirming that it is operating successfully. By employing the outlined procedures, administrators can guarantee a secure, scalable, and efficient environment, ready to support diverse online platform applications and services. Prerequisites Make sure the following requirements are satisfied before starting the installation of the Apache web server on Ubuntu 22.04 to lower the possibility of mistakes and guarantee a flawless setup. Ubuntu 22.04 System: Make sure Ubuntu 22.04 is installed on the cloud server or virtual machine. Access Rights: User must have root or sudo access to the platform. Online Connection: In order to download and install Apache and related software, a steady web connection is necessary. Domain Name (optional): Having a registered domain name is advised for anyone wishing to deploy a website. Before configuring the Apache web server, the DNS settings should be set up to point the domain to the server's IP address. System Update Ensure the engine is fully updated prior to starting the installation process. System updates reduce compatibility problems during installation by verifying that every software packages, libraries, and dependencies are up to date. Log in with administrative credentials to the server. Execute the following command for updating the system's package index. sudo apt update This will retrieve the most recent data on software and package versions from the repositories. Subsequently, upgrade the installed packages to the most recent versions by deploying the instruction below:  sudo apt upgrade Apache Installation Ubuntu's default repositories contain Apache. Employ the following command to install the core Apache package and its dependencies.  sudo apt install apache2 -y Once the installation is finished, validate if Apache was successfully installed by looking up its version. apache2 -v Next, verify that Apache is operational. sudo systemctl status apache2 Permit Apache Traffic Through the Firewall Apache traffic must be permitted if your server has the Uncomplicated Firewall (UFW) enabled. Add the necessary rules. First, make sure SSH connections are allowed: sudo ufw allow ssh Then, add the specific rule for Apache: sudo ufw allow 'Apache Full' To verify that the Apache traffic is allowed, check the status of the UFW rules. sudo ufw status Test Apache Installation Launch an internet browser and navigate to your server's IP address to make sure Apache is operating. The default Apache "Welcome Page" will be displayed if Apache is installed correctly. http://server-ip You can find the server's IP address on the server Dashboard in your Hostman control panel. You can also determine the IP address for the server by employing the command below. Check the inet field for the IP address. ip addr show In this case, the IP address of the server is 166.1.227.224. So we visit it in the web browser: http:// 166.1.227.224 Control the Apache Service To manage the Apache service, use these fundamental commands: sudo systemctl start apache2  – employ this to initialise Apache engine. sudo systemctl stop apache2  – employ this command to halt the Apache. sudo systemctl restart apache2  – employ this to reinitialise the Apache engine. sudo systemctl enable apache2  – to configure the Apache engine to start automatically upon reboot. sudo systemctl disable apache2  – to prevent the Apache service from launching automatically after a system reboot. Set up Apache (Optional) The Apache configuration files are located in /etc/apache2/. Typical configuration tasks include the techniques mentioned below. sudo nano /etc/apache2/apache2.conf This will open the main configuration file for modifying. This file manages a variety of server settings, including Apache's behavior, security protocols, and how it processes incoming web requests. /etc/apache2/sites-available This is a directory that houses virtual host configuration files in the Apache web server's configuration hierarchy. By setting distinct domains or subdomains, virtual hosts enable users to operate several websites or apps on a single Apache server. Virtual hosts allow administrators to employ several websites or web applications on a single Apache server, making it an effective solution for minimising infrastructure expenses and simplifying server management. This capability streamlines operations by consolidating multiple sites onto one server, reducing the need for additional hardware and enhancing resource utilisation. sudo a2ensite apache-config.conf This method is utilised to activate a site-specific Apache web server configuration file on systems located on /etc/apache2/sites-available/. Whenever this command is executed, the file /etc/apache2/sites-available/apache-config.conf is linked to /etc/apache2/sites-enabled/. sudo a2dissite apache-config.conf This method is used to disable a site-specific Apache web server configuration file on systems located on /etc/apache2/sites-available/. Whenever this command is executed, the file /etc/apache2/sites-available/apache-config.conf is unlinked to /etc/apache2/sites-enabled/. sudo apache2ctl configtest The goal is to verify the syntax of the configuration files for the Apache web server prior to making any modifications or restarting the service. It makes sure that the configuration files don't contain any invalid directives or syntax mistakes that could cause Apache to crash on a restart or reload. sudo systemctl reload apache2 This is used to refresh the settings of the Apache web server without halting or disrupting ongoing connections whenever there is change made on the apache configuration. Secure Apache with SSL (Optional) Installing Certbot and the Apache plugin with the command below is the standard way to secure the Apache server with HTTPS. sudo apt install certbot python3-certbot-apache -y Use Certbot to set up SSL automatically by employing the command below. Set up the SSL certificate by following the instructions on prompt (see highlighted in yellow). sudo certbot --apache Conclusion One essential step in hosting web apps or providing webpages on Ubuntu 22.04 is installing and configuring the Apache web server. Administrators can create a dependable and expandable web server environment by following the described procedures, which include installing and maintaining virtual hosts as well as testing settings. By ensuring the integrity of configuration files, operations such as sudo apache2ctl configtest lower the possibility of errors or outages. Because of its adaptability, stability, and broad community support, Apache remains a fundamental component of web hosting solutions, making it a necessary competency for both developers and IT professionals.
14 January 2025 · 6 min to read
Python

How to Split a String Using the split() Method in Python

Working with strings is integral to many programming tasks, whether it involves processing user input, analyzing log files, or developing web applications. One of the fundamental tools that simplifies string manipulation in Python is the split() method. This method allows us to easily divide strings into parts based on specified criteria, making data processing and analysis more straightforward. In this article, we'll take a detailed look at the split() method, its syntax, and usage features. You'll learn how to use this method for solving everyday tasks and see how powerful it can be when applied correctly. Regardless of your programming experience level, you'll find practical tips and techniques to help you improve your string-handling skills in Python. What is the split() Method? The split() method is one of the core tools for working with strings in Python. It is designed to split a string into individual parts based on a specified delimiter, creating a list from these parts. This method is particularly useful for dividing text into words, extracting parameters from a string, or processing data separated by special characters, such as commas or tabs. The key idea behind the split() method is to transform a single string into a set of smaller, more manageable elements. This significantly simplifies data processing and allows programmers to perform analysis and transformation tasks more quickly and efficiently. Syntax of split() The split() method is part of Python's standard library and is applied directly to a string. Its basic syntax is as follows: str.split(sep=None, maxsplit=-1) Let’s break down the parameters of the split() method: sep (separator) This is an optional parameter that specifies the character or sequence of characters used as the delimiter for splitting the string. If sep is not provided or is set to None, the method defaults to splitting the string by whitespace (including spaces, tabs, and newline characters). If the string starts or ends with the delimiter, it is handled in a specific way. maxsplit This optional parameter defines the maximum number of splits to perform. By default, maxsplit is -1, which means there is no limit, and the string will be split completely. If maxsplit is set to a positive number, the method will split the string only the specified number of times, leaving the remaining part of the string as the last element in the resulting list. These parameters make it possible to customize split() to meet the specific requirements of your task. Let’s explore practical applications of split() with various examples to demonstrate its functionality and how it can be useful in daily data manipulation tasks. Examples of Using the split() Method To better understand how the split() method works, let's look at several practical examples that demonstrate its capabilities and applicability in various scenarios. Splitting a String by Spaces The most common use of the split() method is to break a string into words. By default, if no separator is specified, split() divides the string by whitespace characters. text = "Hello world from Python" words = text.split() print(words) Output: ['Hello', 'world', 'from', 'Python'] Splitting a String by a Specific Character If the data in the string is separated by another character, such as commas, you can specify that character as the sep argument. vegetable_list = "carrot,tomato,cucumber" vegetables = vegetable_list.split(',') print(vegetables) Output: ['carrot', 'tomato', 'cucumber'] Splitting a String a Specified Number of Times Sometimes, it’s necessary to limit the number of splits. The maxsplit parameter allows you to specify the maximum number of splits to be performed. text = "one#two#three#four" result = text.split('#', 2) print(result) Output: ['one', 'two', 'three#four'] In this example, the string was split into two parts, and the remaining portion after the second separator, 'three#four', was kept in the last list element. These examples demonstrate how flexible and useful the split() method can be in Python. Depending on your tasks, you can adapt its use to handle more complex string processing scenarios. Using the maxsplit Parameter The maxsplit parameter provides the ability to limit the number of splits a string will undergo. This can be useful when you only need a certain number of elements and do not require the entire string to be split. Let's take a closer look at how to use this parameter in practice. Limiting the Number of Splits Imagine you have a string containing a full file path, and you only need to extract the drive and the folder: path = "C:/Users/John/Documents/report.txt" parts = path.split('/', 2) print(parts) Output: ['C:', 'Users', 'John/Documents/report.txt'] Using maxsplit for Log File Processing Consider a string representing a log entry, where each part of the entry is separated by spaces. You are only interested in the first two fields—date and time. log_entry = "2024-10-23 11:15:32 User login successful" date_time = log_entry.split(' ', 2) print(date_time[:2]) Output: ['2024-10-23', '11:15:32'] In this case, we split the string twice and extract only the date and time, ignoring the rest of the entry. Application to CSV Data Sometimes, data may contain delimiter characters that you want to ignore after a certain point. csv_data = "Name,Email,Phone,Address" columns = csv_data.split(',', 2) print(columns) Output: ['Name', 'Email', 'Phone,Address'] Here, we limit the number of splits to keep the fields 'Phone' and 'Address' combined. The maxsplit parameter adds flexibility and control to the split() method, making it ideal for more complex data processing scenarios. Working with Delimiters Let’s examine how the split() method handles delimiters, including its default behavior and how to work with consecutive and multiple delimiters. Splitting by Default When no explicit delimiter is provided, the split() method splits the string by whitespace characters (spaces, tabs, and newlines). Additionally, consecutive spaces will be interpreted as a single delimiter, which is particularly useful when working with texts that may contain varying numbers of spaces between words. text = "Python is a versatile language" words = text.split() print(words) Output: ['Python', 'is', 'a', 'versatile', 'language'] Using a Single Delimiter Character If the string contains a specific delimiter, such as a comma or a colon, you can explicitly specify it as the sep argument. data = "red,green,blue,yellow" colors = data.split(',') print(colors) Output: ['red', 'green', 'blue', 'yellow'] In this case, the method splits the string wherever a comma is encountered. Working with Consecutive and Multiple Delimiters It’s important to note that when using a single delimiter character, split() does not treat consecutive delimiters as one. Each occurrence of the delimiter results in a new element in the resulting list, even if the element is empty. data = "one,,two,,,three" items = data.split(',') print(items) Output: ['one', '', 'two', '', '', 'three'] Splitting a String by Multiple Characters There are cases where you need to split a string using multiple delimiters or complex splitting rules. In such cases, it is recommended to use the re module and the re.split() function, which supports regular expressions. import re beverage_data = "coffee;tea juice|soda" beverages = re.split(r'[;|\s]', beverage_data) print(beverages) Output: ['coffee', 'tea', 'juice', 'soda'] In this example, a regular expression is used to split the string by several types of delimiters. Tips for Using the split() Method The split() method is a powerful and flexible tool for working with textual data in Python. To fully leverage its capabilities and avoid common pitfalls, here are some useful recommendations: Consider the Type of Delimiters When choosing a delimiter, make sure it matches the nature of the data. For instance, if the data contains multiple spaces, it might be more appropriate to use split() without explicitly specifying delimiters to avoid empty strings in the list. Use maxsplit for Optimization If you know that you only need a certain number of elements after splitting, use the maxsplit parameter to improve performance. This will also help avoid unexpected results when splitting long strings. Use Regular Expressions for Complex Cases The split() method with regular expressions enables solving more complex splitting tasks, such as when data contains multiple types of delimiters. Including the re library for this purpose significantly expands the method’s capabilities. Handle Empty Values When splitting a string with potentially missing values (e.g., when there are consecutive delimiters), make sure your code correctly handles empty strings or None. data = "value1,,value3" result = [item for item in data.split(',') if item] Validate Input Data Always consider potential errors, such as incorrect delimiters or unexpected data formats. Adding checks for values before calling split() can prevent many issues related to incorrect string splitting. Suitability for Use Remember that split() is unsuitable for processing more complex data structures, such as nested strings with quotes or data with escaped delimiters. In such cases, consider using specialized modules, such as csv for handling CSV formats. Following these tips, you can effectively use the split() method and solve textual data problems in Python. Understanding the subtleties of string splitting will help you avoid errors and make your code more reliable and understandable. Conclusion The split() method is an essential part of string handling in Python, providing developers with flexible and powerful tools for text splitting and data processing. In this article, we explored various aspects of using the split() method, including its syntax, working with parameters and delimiters, as well as practical examples and tips for its use. Check out our app platform to find Python applications, such as Celery, Django, FastAPI and Flask.
13 January 2025 · 8 min to read
Python

How to Convert a List to a Dictionary in Python

Python offers several fundamental data structures for storing data. Among the most popular are: List: Values with indices. Dictionary: Values with keys. Converting data from one type to another is essential to any dynamically typed programming language. Python, of course, is no exception. This guide will explain in detail what lists and dictionaries are and demonstrate various ways to convert one type to another. All examples in this article were executed using the Python interpreter version 3.10.12 on the Ubuntu 22.04 operating system, running on a Hostman cloud server. The list Type A list in Python is an ordered data structure of the "index-value" type. To create a list, use square brackets with values separated by commas: my_list = [False, True, 2, 'three', 4, 5] The list structure can be displayed in the console: print(my_list) The output will look like this: [False, True, 2, 'three', 4, 5] Accessing list values is done via indices: print(my_list[0]) # Output: False print(my_list[1]) # Output: True print(my_list[2]) # Output: 2 print(my_list[3]) # Output: three print(my_list[4]) # Output: 4 print(my_list[5]) # Output: 5 The dict Type A dictionary in Python is an unordered data structure of the "key-value" type. To create a dictionary, use curly braces with keys and values separated by colons and each pair separated by commas: my_dict = { 'James': '357 99 056 050', 'Natalie': '357 96 540 432', 'Kate': '357 96 830 726' } You can display the dictionary structure in the console as follows: print(my_dict) The output will look like this: {'James': '357 99 056 050', 'Natalie': '357 96 540 432', 'Kate': '357 96 830 726'} Accessing dictionary values is done via keys: print(my_dict['James']) # Output: 357 99 056 050 print(my_dict['Natalie']) # Output: 357 96 540 432 print(my_dict['Kate']) # Output: 357 96 830 726 Converting a List to a Dictionary You can convert a list to a dictionary in several ways: Use the dict.fromkeys() function, which creates a new dictionary with keys from the list. Use a dictionary comprehension with auxiliary functions and conditional operators. The latter option provides more flexibility for generating new dictionaries from existing lists. Creating Dictionary Keys from a List Using dict.fromkeys() The simplest way to create a dictionary from a list is to take the elements of a list instance and make them the keys of a dict instance. Optionally, you can add a default value for all keys in the new dictionary. This can be achieved using the standard dict.fromkeys() function. With this method, you can set a default value for all keys but not for individual keys. Here is an example of creating such a dictionary with keys from a list: objects = ['human', 'cat', 'alien', 'car'] # list of objects objects_states = dict.fromkeys(objects, 'angry') # create a dictionary with a default value for all keys objects_states_empty = dict.fromkeys(objects) # create a dictionary without specifying default values print(objects_states) # output the created dictionary with values print(objects_states_empty) # output the created dictionary without values Console output: {'human': 'angry', 'cat': 'angry', 'alien': 'angry', 'car': 'angry'} {'human': None, 'cat': None, 'alien': None, 'car': None} Creating a Dictionary from a List Using Dictionary Comprehension Another way to turn a list into dictionary keys is by using dictionary comprehension. This method is more flexible and allows for greater customization of the new dictionary. In its simplest form, the comprehension iterates over the list and copies all its elements as keys into a new dictionary, assigning them a specified default value. Here’s how to create a dictionary from a list using dictionary comprehension: objects = ['human', 'cat', 'alien', 'car'] objects_states = {obj: 'angry' for obj in objects} # dictionary comprehension with a string as the default value objects_states_empty = {obj: None for obj in objects} # dictionary comprehension with a default value of None print(objects_states) print(objects_states_empty) Console output: {'human': 'angry', 'cat': 'angry', 'alien': 'angry', 'car': 'angry'} {'human': None, 'cat': None, 'alien': None, 'car': None} In Python, the None object is a special value (null in most programming languages) that represents the absence of a value. The None object has a type of NoneType: print(type(None))  # Output: <class 'NoneType'> Creating a Dictionary from a List Using Dictionary Comprehension and the zip() Function A more advanced method is to use two lists to generate a dictionary: one for the keys and the other for their values. For this purpose, Python provides the zip() function, which allows iteration over multiple objects simultaneously. In simple loops, we can use this function like this: objects = ['human', 'cat', 'alien', 'car'] states = ['walking', 'purring', 'hiding', 'driving'] for obj, state in zip(objects, states): print(obj, state) The console output will be: human walking cat purring alien hiding car driving Thanks to this function, dictionary comprehension can simultaneously use elements from one list as keys and elements from another as values. In this case, the syntax for dictionary comprehension is not much different from a simple iteration: objects = ['human', 'cat', 'alien', 'car'] # list of future dictionary keys states = ['walking', 'purring', 'hiding', 'driving'] # list of future dictionary values objects_states = {obj: state for obj, state in zip(objects, states)} # dictionary comprehension iterating over both lists print(objects_states) Console output: {'human': 'walking', 'cat': 'purring', 'alien': 'hiding', 'car': 'driving'} A natural question arises: what happens if one of the lists is shorter than the other? objects = ['human', 'cat', 'alien', 'car'] states = ['walking', 'purring'] objects_states = {obj: state for obj, state in zip(objects, states)} print(objects_states) The output will be: {'human': 'walking', 'cat': 'purring'} Thus, iteration in the dictionary comprehension stops at the shortest list. The code above can be written in a very compact form using the dict() constructor: objects = ['human', 'cat', 'alien', 'car'] states = ['walking', 'purring', 'hiding', 'driving'] objects_states = dict(zip(objects, states)) # create a dictionary from two lists without a for loop print(objects_states) The console output will be the same as in the previous examples: {'human': 'walking', 'cat': 'purring', 'alien': 'hiding', 'car': 'driving'} Creating a Dictionary with zip() and Conditional Logic In real-world applications, logic is often more complex than the simple examples shown earlier. Sometimes, you need to convert lists into dictionaries while applying specific conditions. For instance, some elements might need modification before inclusion in the dictionary or might not be included at all. This can be achieved using conditions in dictionary comprehensions. For example, we can exclude specific elements from the resulting dictionary: objects = ['human', 'cat', 'alien', 'car'] states = ['walking', 'purring', 'hiding', 'driving'] objects_states = {obj: state for obj, state in zip(objects, states) if obj != 'alien'} # Protect Earth from unknown extraterrestrial influence print(objects_states) Console output: {'human': 'walking', 'cat': 'purring', 'car': 'driving'} We can refine the selection criteria further by introducing multiple conditions: objects = ['human', 'cat', 'alien', 'car'] states = ['walking', 'purring', 'hiding', 'driving'] objects_states = {obj: state for obj, state in zip(objects, states) if obj != 'alien' if obj != 'cat'} # Exclude the alien and the cat—who might be a disguised visitor from another galaxy print(objects_states) Console output: {'human': 'walking', 'car': 'driving'} When using multiple if statements in a dictionary comprehension, they behave as if connected by a logical and operator. You can make dictionary generation even more flexible by combining if and else operators: objects = ['human', 'cat', 'alien', 'car'] states = ['walking', 'purring', 'hiding', 'driving'] # In this example, all string elements in the first list are longer than those in the second list, except for 'cat' objects_states = { obj: ('[SUSPICIOUS]' if len(obj) < len(state) else 'calmly ' + state) for obj, state in zip(objects, states) } # Mark the suspicious 'cat' appropriately and slightly modify other values print(objects_states) Console output: {'human': 'calmly walking', 'cat': '[SUSPICIOUS]', 'alien': 'calmly hiding', 'car': 'calmly driving'} Creating a Complex Dictionary from a Single List In the earlier examples, we created dictionaries from two separate lists. But what if the keys and values needed for the new dictionary are contained within a single list? In such cases, the logic of the dictionary comprehension needs to be adjusted: objects_and_states = [ 'human', 'walking', 'cat', 'purring', 'alien', 'hiding', 'car', 'driving' ] # Keys and values are stored sequentially in one list objects_states = { objects_and_states[i]: objects_and_states[i + 1] for i in range(0, len(objects_and_states), 2) } # The `range` function specifies the start, end, and step for iteration: range(START, STOP, STEP) print(objects_states) Console output: {'human': 'walking', 'cat': 'purring', 'alien': 'hiding', 'car': 'driving'} Sometimes, a list might contain nested dictionaries as elements. The values of these nested dictionaries can also be used to create a new dictionary. Here’s how the logic changes in such cases: objects = [ {'name': 'human', 'state': 'walking', 'location': 'street'}, {'name': 'cat', 'state': 'purring', 'location': 'windowsill'}, {'name': 'alien', 'state': 'hiding', 'location': 'spaceship'}, {'name': 'car', 'state': 'driving', 'location': 'highway'} ] objects_states = { obj['name']: obj['state'] for obj in objects } # Extract 'name' as key and 'state' as value print(objects_states) Console output: {'human': 'walking', 'cat': 'purring', 'alien': 'hiding', 'car': 'driving'} This approach enables handling more complex data structures, such as lists of dictionaries, by targeting specific key-value pairs from each nested dictionary. Converting a Dictionary to a List Converting a dictionary into a list in Python is a straightforward task, often better described as extracting data. From a single dictionary, you can derive several types of lists: A list of keys A list of values A list of key-value pairs Here’s how it can be done: objects_states = { 'human': 'walking', 'cat': 'purring', 'alien': 'hiding', 'car': 'driving' } # Convert dictionary components to lists using the `list()` function objects_keys = list(objects_states.keys()) # List of keys objects_values = list(objects_states.values()) # List of values objects_items = list(objects_states.items()) # List of key-value pairs print(objects_keys) print(objects_values) print(objects_items) Console output: ['human', 'cat', 'alien', 'car'] ['walking', 'purring', 'hiding', 'driving'] [('human', 'walking'), ('cat', 'purring'), ('alien', 'hiding'), ('car', 'driving')] Conclusion Lists and dictionaries are fundamental data structures in Python, each offering distinct ways of storing and accessing data. Dictionaries are more informative than lists, storing data as key-value pairs, whereas lists store values that are accessed by index. Converting a dictionary into a list is straightforward, requiring no additional data since you’re simply extracting keys, values, or their pairs. Converting a list into a dictionary, on the other hand, requires additional data or rules to map the list elements to dictionary keys and values. There are a few methods to convert a List to Dictionary Tool Key Values Syntax dict.fromkeys() Common new_dict = dict.fromkeys(old_list) Dictionary Comprehension Common new_dict = {new_key: 'any value' for new_key in old_list} Dict Comp + zip() Unique new_dict = {new_key: old_val for new_key, old_val in zip(list1, list2)} Dict Comp + zip() + if Unique new_dict = {new_key: old_val for new_key, old_val in zip(list1, list2) if ...} Dict Comp + zip() + if-else Unique new_dict = {new_key: (... if ... else ...) for new_key, old_val in zip(list1, list2)} Complex lists may require more intricate dictionary comprehension syntax. Techniques shown in this guide, such as using zip() and range() for iterations, help handle such cases. Converting a dictionary to a list is also possible in several ways, but it is much simpler. Tool Extracts Syntax list.keys() Keys list(old_dict.keys()) list.values() Values list(old_dict.values()) list.items() Key-Value Pairs list(old_dict.items()) Python offers flexible and efficient ways to convert structured data types between lists and dictionaries, enabling powerful manipulation and access.
13 January 2025 · 11 min to read
Python

Dictionaries in Python

A dictionary (or dict) is an unordered data structure in Python (unlike a list) that takes the form of "key-value" pairs. In simpler terms, a dictionary is like a notebook with no specific order, where each number (value) is associated with a specific name (key). James +357 99 056 050 Julia +357 96 540 432 Alexander +357 96 830 726 Each key in a Python dictionary is completely unique, but the values can be repeated. For example, if you add a new entry with the name "Julia" (value) and a new number (key), the entry will not duplicate but instead update the existing value. To find a specific number, you need to provide the name. This makes Python dictionaries a convenient way to search through large datasets. The following data types can be used as keys: Strings Numbers (integers and floats) Tuples Values can be any data type, including other dictionaries and lists. Creating a Dictionary This guide uses Python version 3.10.12. Using Curly Braces {} The simplest and most straightforward way to create a dictionary is by using curly braces. For example, this creates an empty dictionary with no keys or values: empty_dictionary = {} Here’s how to create a dictionary with keys and values inside: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} The names in quotes are the keys, and the numbers are their values. The previously shown table can be represented as a dictionary like this: team_phones = { "James": "+357 99 056 050", "Julia": "+357 96 540 432", "Alexander": "+357 96 830 726" } In this case, the values are of string type, not numeric. By the way, you can also use single quotes instead of double quotes: team_phones = { 'James': '+357 99 056 050', 'Julia': '+357 96 540 432', 'Alexander': '+357 96 830 726' } Using the dict() Function As with many other types of variables, a dictionary can be created using its corresponding function. For example, this creates an empty dictionary: just_dictionary = dict() And this creates a dictionary with keys and values: keys_and_values = [("Alexander", 23), ("Victoria", 43), ("Eugene", 26), ("Meredith", 52), ("Maria", 32)] team_ages = dict(keys_and_values) In this case, a list of so-called tuples — pairs of "key-value" — is created first. However, there is a more concise way to create a dictionary using the function: team_ages = dict(Alexander = 23, Victoria = 43, Eugene = 26, Meredith = 52, Maria = 32) Here, each function argument becomes a key with a corresponding value in the new dictionary. Using the dict.fromkeys() Function Another way to create a dictionary is by converting a list into a dictionary. There are a few nuances to this approach: The elements of the list become the keys of the new dictionary. You can specify a default value for all keys at once, rather than for each key individually. For example, this creates a dictionary where the values of the keys will be empty: team_names = ["Alexander", "Victoria", "Eugene", "Meredith", "Maria"] # list with keys team_ages = dict.fromkeys(team_names) print(team_ages) The console output will be: {'Alexander': None, 'Victoria': None, 'Eugene': None, 'Meredith': None, 'Maria': None} And this creates a dictionary with a specified value, which will be common for all keys: team_names = ["Alexander", "Victoria", "Eugene", "Meredith", "Maria"] team_ages = dict.fromkeys(team_names, 0) # setting the default value as the second argument print(team_ages) The console output will be: {'Alexander': 0, 'Victoria': 0, 'Eugene': 0, 'Meredith': 0, 'Maria': 0} Dictionary Comprehension A more unconventional way to create a dictionary is by generating it from other data using a so-called dictionary comprehension, which is a compact for loop with rules for dictionary generation written inside. In this case, the generator loop iterates through the data structure from which the dictionary is created. For example, here’s how to create a dictionary from a list with a default value for all keys: team_names = ["Alexander", "Victoria", "Eugene", "Meredith", "Maria"] team_ages = {name: 0 for name in team_names} # dictionary generator with 0 as the default value print(team_ages) The console output will be identical to the previous example: {'Alexander': 0, 'Victoria': 0, 'Eugene': 0, 'Meredith': 0, 'Maria': 0} However, the main advantage of this method is the ability to assign individual values to each key. For this, you need to prepare two lists and slightly modify the basic dictionary comprehension syntax: team_names = ["Alexander", "Victoria", "Eugene", "Meredith", "Maria"] team_numbers = [23, 43, 26, 52, 32] team_ages = {name: age for name, age in zip(team_names, team_numbers)} # using the zip() function to iterate over two lists simultaneously print(team_ages) The zip() function combines the two lists into a list of tuples, which is then iterated over in the comprehension loop. In this case, the console output will be: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} There is also a more complex variant that generates a dictionary from a single list containing both keys and values: team_data = ["Alexander", 23, "Victoria", 43, "Eugene", 26, "Meredith", 52, "Maria", 32] # keys and values are stored sequentially in one list team_ages = {team_data[i]: team_data[i+1] for i in range(0, len(team_data), 2)} # loop runs through the list with a step of 2 print(team_ages) In this example, the range() function sets the length and iteration step for the loop. The console output will be identical to the previous ones: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} Adding Elements You can add an element to a dictionary by specifying a previously non-existent key in square brackets and assigning a new value to it: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_ages["Catherine"] = 28 # Adding a new key-value pair print(team_ages) The console output will be: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32, 'Catherine': 28} Modifying Elements Modifying an element is syntactically the same as adding one, except that the element already exists in the dictionary: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_ages["Victoria"] = 44 # Updating the existing value print(team_ages) The console output will be: {'Alexander': 23, 'Victoria': 44, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} Accessing Elements You can access the values in a dictionary using square brackets with the key: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} print(team_ages["Eugene"]) The console output will be: 26 Or with a more visual example using the previously shown table: team_phones = { "James": "+357 99 056 050", "Julia": "+357 96 540 432", "Alexander": "+357 96 830 726" } print(team_phones["Julia"]) The console output will be: +357 96 540 432 Removing Elements You can remove an element from a dictionary using the del keyword: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} del team_ages["Victoria"] # Deleting the element with the key "Victoria" print(team_ages) The console output will not contain the deleted element: {'Alexander': 23, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} Managing Elements A dictionary in Python has a set of special methods for managing its elements — both keys and values. Many of these methods duplicate the previously shown functions for adding, modifying, and deleting elements. The dict.update() Function This method adds new elements to a dictionary by passing another dictionary as an argument: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_ages.update({ "John": 32, "Catherine": 28 }) print(team_ages) The output in the console will be: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32, 'John': 32, 'Catherine': 28} The same result can be achieved by pre-creating a dictionary with the elements to be added: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_add = {"John": 32, "Catherine": 28} team_ages.update(team_add) print(team_ages) Again, the output will be the same: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32, 'John': 32, 'Catherine': 28} The dict.get() Function You can access the value of a dictionary not only with square brackets but also through the corresponding function: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} print(team_ages.get("Victoria")) print(team_ages["Victoria"]) Both console outputs will be: 4343 Now, what happens if a non-existing key is passed as an argument: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} print(team_ages.get("Anastasia")) The console output will be: None However, the main feature of get() compared to square brackets is the ability to specify a value for a non-existing key as the second argument: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} print(team_ages.get("Anastasia", "Non-existent employee")) In this case, the console output will be: Non-existent employee When using square brackets, you would need to use a try/except block to handle cases where you are not sure if the key exists. The dict.pop() Function In dictionaries, there is a specific function to delete an element by key: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_ages.pop("Alexander") print(team_ages) The console output will be: {'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} The dict.popitem() Function Instead of deleting a specific element by key, you can delete the last added item: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_add = {"John": 32, "Catherine": 28} team_ages.update({"John": 32}) print(team_ages) team_ages.popitem() print(team_ages) The console output will show the dictionary with the added element and then its contents after the element is removed: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32, 'John': 32} {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} The dict.clear() Function You can completely clear a dictionary using the corresponding method: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_ages.clear() print(team_ages) The console output will show an empty dictionary: {} The dict.copy() Function You can fully copy a dictionary: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} team_ages_copy = team_ages.copy() print(team_ages) print(team_ages_copy) The console output will contain the same content from two different dictionaries: {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} {'Alexander': 23, 'Victoria': 43, 'Eugene': 26, 'Meredith': 52, 'Maria': 32} The dict.setdefault() Function Sometimes, the mechanics of adding or retrieving a key are not enough. Often, you need more complex behavior. For example, in some cases, you need to check for the presence of a key and immediately get its value, and if the key doesn't exist, it should be automatically added. Python provides a special method for this operation: team_ages = {"Alexander": 23, "Victoria": 43, "Eugene": 26, "Meredith": 52, "Maria": 32} print(team_ages.setdefault("Alexander")) # This key already exists print(team_ages.setdefault("John")) # This key doesn't exist, so it will be created with the value None print(team_ages.setdefault("Catherine", 29)) # This key doesn't exist, so it will be created with the value 29 The console output will show results for all requested names, regardless of whether they existed at the time of the function call: 23None29 Dictionary Transformation You can extract data from a dictionary's keys and values. Typically, this extraction operation is performed to convert the dictionary into another data type, such as a list. There are several functions for extracting data from a dictionary in Python: dict.keys() — returns an object with the dictionary's keys dict.values() — returns an object with the dictionary's values dict.items() — returns an object with "key-value" tuples Here's an example of how to extract data from a dictionary and convert it into a list: team_phones = { "James": "+357 99 056 050", "Julia": "+357 96 540 432", "Alexander": "+357 96 830 726" } # All returned objects are converted into lists using the list() function team_names = list(team_phones.keys()) # List of dictionary keys team_numbers = list(team_phones.values()) # List of dictionary values team_all = list(team_phones.items()) # List of "key-value" pairs print(team_names) print(team_numbers) print(team_all) The console output will be: ['James', 'Julia', 'Alexander'] ['+357 99 056 050', '+357 96 540 432', '+357 96 830 726'] [('James', '+357 99 056 050'), ('Julia', '+357 96 540 432'), ('Alexander', '+357 96 830 726')] In the above example, the returned objects from the dictionary are explicitly converted into lists. However, this step is not necessary: team_phones = { "James": "+357 99 056 050", "Julia": "+357 96 540 432", "Alexander": "+357 96 830 726" } print(team_phones.keys()) print(team_phones.values()) print(team_phones.items()) The console output will be: dict_keys(['James', 'Julia', 'Alexander']) dict_values(['+357 99 056 050', '+357 96 540 432', '+357 96 830 726']) dict_items([('James', '+357 99 056 050'), ('Julia', '+357 96 540 432'), ('Alexander', '+357 96 830 726')]) Conclusion In Python, a dictionary is an unordered data structure in the form of "key-value" pairs, with which you can perform the following operations: Creating a dictionary from scratch Generating a dictionary from other data Adding elements Modifying elements Accessing elements Removing elements Managing elements Transforming the dictionary Thus, a dictionary solves many problems related to finding a specific value within a large data structure — any value from the dictionary is retrieved using its corresponding key. If you want to build a web service using Python, you can rent a cloud server at competitive prices with Hostman.
10 January 2025 · 12 min to read
Python

How to Remove Spaces from a String in Python

Strings are one of the fundamental data types in Python, storing a sequence of characters. With strings, you can perform many operations: splitting, joining, replacing, comparing, and more. Sometimes, it's necessary to format strings by removing unnecessary characters, such as spaces. This article will cover the methods available in Python (version 3.10.12) for removing spaces from strings. Removing Spaces from the Start and End Often, we need to remove only extra spaces, such as those at the start or end of a string. Python provides several similar methods for this purpose: strip() removes spaces from both the string's start and end. lstrip() removes spaces only from the start. rstrip() removes spaces only from the end. Here’s an example of how to clean up a string by removing spaces at the edges: text_before = " This is a string with spaces " text_after = text_before.strip() text_after_left = text_before.lstrip() text_after_right = text_before.rstrip() print(text_after) print(text_after_left) print(text_after_right) Console output: This is a string with spaces This is a string with spaces This is a string with spaces Removing All Spaces In some cases, you may need to remove all spaces entirely. This can be done by replacing every space character with an empty string: text_before = " This is a string with spaces " text_after = text_before.replace(' ', '') print(text_after) Console output: Thisisastringwithspaces Another way to remove all spaces is to use the translate() method. While less intuitive, it can be more flexible in certain scenarios: text_before = " This is a string with spaces " text_after = text_before.translate({ord(' '): None}) print(text_after) Console output: Thisisastringwithspaces The translate() function takes a dictionary as an argument, where the keys are ASCII codes of characters to be replaced, and the values are the replacement characters. The ord() function converts a character to its corresponding ASCII code. With translate(), you can replace multiple characters at once. For example: text_before1 = " This is a string with spaces " text_before2 = " 1 2 3 4 5 " text_before3 = " { 'someData': 100, 'otherData': 'information' } " space_table = str.maketrans({' ': None}) text_after1 = text_before1.translate(space_table) text_after2 = text_before2.translate(space_table) text_after3 = text_before3.translate(space_table) print(text_after1) print(text_after2) print(text_after3) Console output: Thisisastringwithspaces 12345 {'someData':100,'otherData':'information'} Removing Repeated Spaces The simplest way to remove all repeated spaces in a string is to perform the following steps: Split the string using the split() function by spaces as delimiters, resulting in a list of substrings. Join the substrings from the list back into a single string using the join() function with a single space as the separator. Here’s how this can be done: text_before = " This is a string with spaces " # Split the string into substrings; spaces are the default delimiter text_splitted = text_before.split() # Join the substrings into a single string using a space as the delimiter text_after = ' '.join(text_splitted) print(text_after) In the console, you’ll see the formatted string without extra spaces: This is a string with spaces You can write the same operations more concisely: text_before = " This is a string with spaces " text_after = ' '.join(text_before.split()) print(text_after) The console output will remain the same: This is a string with spaces Using this method, you can also replace spaces with any other character: text_before = " This is a string with spaces " text_after = '_'.join(text_before.split()) print(text_after) In this case, the console output will be: This_is_a_string_with_spaces Removing Spaces Using Regular Expressions The methods shown earlier are effective for simple scenarios. However, strings often have more complex patterns, requiring advanced methods to remove spaces. A highly flexible way to handle string modifications is by using regular expressions. Here’s an example: import re # Import the module for working with regular expressions # A string containing sequences of two or more spaces, as well as some single spaces text_before = " This is a string with spaces . " # Replace all sequences of two or more spaces with a single space text_after = re.sub(r"\s+", " ", text_before) print(text_after) The console output will be a string where only single spaces remain: This is a string with spaces . This example introduces some problems: Multiple spaces before the period at the end are replaced with a single space. However, there should not be any space before the period. A sequence of spaces at the start of the string is replaced by a single space. However, there should not be any spaces at the beginning of the string. We can resolve these issues by applying a sequence of transformations: import re text_before = " This is a string with spaces . " # Remove spaces at the start and end of the string using the OR operator (|) text_after = re.sub(r"^\s*|\s*$", "", text_before) # Replace all repeated spaces with a single space text_after = re.sub(r"\s+", " ", text_after) # Replace all periods surrounded by spaces with just a period text_after = re.sub(r"\s*[.]\s*", ".", text_after) print(text_after) The console output will now contain a properly formatted string without unnecessary spaces: This is a string with spaces. Here: \s: Matches any whitespace character (spaces, tabs, etc.). +: Matches one or more repetitions of the preceding element. *: Matches zero or more repetitions of the preceding element. |: Represents a logical OR, allowing you to combine multiple conditions. ^: Anchors the match at the beginning of the string. $: Anchors the match at the end of the string. When using regular expressions, it’s important to understand the potential structure of the strings being processed to design an appropriate solution. For example: If the string may have periods surrounded by spaces, this must be handled explicitly. The more complex the string patterns, the more intricate the logic for removing spaces becomes. Ultimately, removing spaces from a string in Python often requires a custom solution tailored to the specific case. Removing Spaces Using a Loop For more complex string manipulation (in this case, removing spaces), you can manually check each character in a loop with multiple conditions. This approach offers more flexibility and control over the process. In the simplest case, removing spaces inside a loop looks like this: # Define a function for more complex string processing logic def complexRemoval(string): after = "" for i in string: if not i.isspace(): # The isspace() function checks if the character is a space and returns a boolean result (True or False) after += i return after text_before = " This is a string with spaces . " text_after = complexRemoval(text_before) print(text_after) The console output will contain all the characters of the original string, but without spaces: Thisisastringwithspaces. Clearly, this isn't the desired result, so we need to complicate the logic for removal. To refine the logic, we can introduce a variable to track whether the previous character was a space: def complexRemoval(string): after = "" wasSpace = True # Variable to track if the previous character was a space for i in string: if not i.isspace(): # If the character is not a space if i == '.' and wasSpace: # If we encounter a period and the previous character was a space, remove it after = after[:len(after) - 1] # Remove the last character (space) after += i wasSpace = False elif not wasSpace: # If it's a space but the previous character was not a space after += i wasSpace = True return after # Test cases print(complexRemoval(" This is a string with spaces . ")) print(complexRemoval("Lots of different spaces blah blah blah . Also a period . ")) The output in the console will now show perfectly formatted strings without unnecessary spaces: This is a string with spaces.Lots of different spaces blah blah blah. Also a period. This method allows for more complex processing of spaces in strings, such as removing spaces before periods or handling sequences of spaces efficiently. Conclusion The Python programming language offers a specific set of built-in tools for string manipulation — for example, operations with space characters: Removing spaces at the beginning of a string Removing spaces at the end of a string Removing spaces from both ends of a string Removing all spaces in a string Removing spaces from a string according to specific rules (using regular expressions) Removing spaces according to unique rules (using iteration) Each variant has its own set of methods — most of which we have covered in this guide. If you want to build a web service using Python, you can rent a cloud server at competitive prices with Hostman.
10 January 2025 · 8 min to read
CSS

How to Change the Color of HTML Elements

When working with a webpage, you often need to enrich the markup by adding visual variety. This can be driven by design requirements or personal preferences. There are many ways to make a page more visually appealing, from font choices to the dynamic behavior of content when scrolling. One of the key graphic techniques is changing the background or text color on the page. Modern browsers allow you to flexibly choose background colors or combinations and specify the desired values in a format that suits you. Elements That Can Have Color Almost any HTML element can have its color. The color is applied in different ways depending on what exactly you want to color. For example, if you need to change the color of text in HTML, you can use the color attribute, and for borders around it, the border-color attribute. These attributes can be set either directly in the markup using HTML attributes or in a CSS file linked to the markup. When working with colors in HTML, elements can be roughly divided into two groups: text elements and block elements. In text elements, you set the color of the text and its styling, while in block elements, you set the background and border colors. Text Elements Text elements include, for example, paragraphs or input fields. For these elements, you can use several attributes for visual styling. Let's look at how to change the text color: color: This attribute is used to set the color of the text and any text decoration (such as underline, overline, etc.). background-color: In addition to changing the text color, it is often required to change the background color as well. This attribute is used for such cases. text-shadow: Sometimes, text design on the page requires a shadow. If the shadow color differs from the default, you can set it using the text-shadow attribute. text-decoration-color: When you set a color for a text element using the color attribute, the color is applied to the accompanying text decoration. But if you want to set a different color for underlining, for example, you can use this attribute. caret-color: In specific cases, you may need to style input fields (input, textarea) or elements with the contenteditable attribute. This attribute allows you to color the caret (the vertical cursor) that appears in the fields. Block Elements For block elements, such as div, you can flexibly set background and border colors regardless of the content inside the block. background-color: Adds a fill to the entire area of the block element. This attribute will help if you're wondering how to change the background color in HTML for the entire page. Just add the attribute to the body styles and specify the desired color. outline-color: Sets the color of the outline around the element if an outline style is specified with outline-style. border-color: Allows you to set the color for the borders around the block element. To set the color for each side — top, bottom, right, and left — use the attributes border-top-color, border-bottom-color, border-right-color, and border-left-color respectively. Other Elements In addition to the HTML elements mentioned above, you can also work with the visual design of the page using technologies such as SVG, Canvas, or WebGL. How to Change Text Color in CSS The first step in using color in your markup is to determine how to specify it so that the browser understands how to color the element.  The way you specify the color primarily depends on how specific or complex the color is. For instance, there’s a difference between using a basic color like blue or combining red, green, and blue in different proportions, potentially with transparency. Key CSS Keywords The simplest way to specify a color is by using a keyword, such as green or lightgrey. For example, to use black for text, you would write color: black;, and the browser will automatically understand the color to display. You can find a complete list of reserved color keywords in the documentation. RGB Model RGB stands for Red, Green, and Blue. When you specify a color using the RGB model, you define the color by mixing three primary colors: red, green, and blue. Like in a regular color palette, mixing these colors in varying proportions creates new combinations and shades. The three RGB values are integers between 0 and 255 or percentages from 0 to 100. For example, when you specify rgb(0, 0, 255), you will see the color blue in the browser. Modern browsers also support an extended version of RGB, called RGBA, where you can specify color transparency. This is done by adding a fourth value for transparency in percentage form. For example, blue with 50% transparency would be written as rgba(0, 0, 255, 0.5). HEX Representation A HEX color is a hexadecimal representation of the RGB model. The color code consists of three pairs of hexadecimal digits, each representing the red, green, and blue components respectively. For example, specifying #00ff00 will display green. If each color group contains identical characters (for example, #2211dff), you can use a shorthand representation — #21f. HSL System HSL stands for Hue, Saturation, and Lightness. In this system, the color is not determined by mixing the three parameters. Instead, each component is independent, which makes it easy to adjust the color's saturation or brightness while keeping the same hue. This system allows more control over the color's appearance without altering the basic tone.
09 January 2025 · 5 min to read
Python

How to Check if a Key Exists in a Python Dictionary

A dictionary (dict) in Python is an unordered data structure that uses a "key-value" format. Any value within the dictionary is accessed by explicitly referencing the key associated with the desired value. Attempting to access a non-existent key results in a program error. To avoid such errors, it’s essential to check whether a key exists in a dictionary before trying to access its value. Python provides several built-in methods for this purpose, which we discuss in this tutorial. In this guide, we use Python 3.10.12 running on Ubuntu 22.04. Using the in Operator with a Dictionary The most common way to check if a key exists in a dictionary is by using the in operator in an if/else condition: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'name' if some_key in some_dict: print('The key "' + some_key + '" was found.') else: print('The key "' + some_key + '" was not found.') Here, the in operator returns True if the key is found and False otherwise. Using the in Operator with dict.keys() You can also use the in operator with the list of dictionary keys obtained via the dict.keys() method: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'name' if some_key in some_dict.keys(): print('The key "' + some_key + '" was found.') else: print('The key "' + some_key + '" was not found.') As you can see, the logic is identical to the previous example, except that the dict.keys() method is used instead of the dictionary instance. At first glance, this approach might seem redundant. However, in practical applications, there may be scenarios where you specifically need to work with the list of dictionary keys rather than the dictionary itself. Using dict.keys(), you can elegantly determine if a specified key exists in the dictionary. Using the dict.get() Function You can check for the presence of a key in a dictionary by attempting to retrieve its value using the built-in dict.get() method: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'salary' some_value = some_dict.get(some_key) # Try to fetch the value for the key # If the returned value is None, it indicates the key does not exist if some_value is not None: print('The key "' + some_key + '" was found, and its value is "' + str(some_value) + '".') else: print('The key "' + some_key + '" was not found.') As shown, accessing a non-existent key with dict.get() will not raise an error (as would happen with square bracket access) but will return a None value. However, this method has a potential drawback: the requested key might actually exist in the dictionary, but its value could still be None: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...', 'salary': None} some_key = 'salary' # The key exists, but its value is None some_value = some_dict.get(some_key) # Returns None print('It is unclear if the key "' + some_key + '" exists or if it exists with a value of None.') In such cases, whether the key does not exist or exists with a None value is ambiguous. We can address this issue by using the ability of dict.get() to set a default value for non-existent keys: some_dict1 = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...', 'salary': None} some_dict2 = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'salary' some_value1 = some_dict1.get(some_key, "Salary not specified") some_value2 = some_dict2.get(some_key, "Salary not specified") print('Attempting to access the key "' + some_key + '" returned the value "' + str(some_value1) + '".') print('Attempting to access the key "' + some_key + '" returned the value "' + str(some_value2) + '".') Console output: Attempting to access the key "salary" returned the value "None". Attempting to access the key "salary" returned the value "Salary not specified". If you attempt to retrieve the value of a non-existent key using square brackets, it will always result in an error. In the future, this error can be handled using a try/except block, thereby determining whether the key actually exists. try/except Exception Handling You can check if a key exists in a dictionary by handling errors with try/except—a direct, "straightforward" approach. In this method, if accessing the key raises an error, it indicates that the key does not exist. Conversely, if no error is raised, the key exists. To implement this, wrap the key access in a try/except block: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'name' try: some_value = some_dict[some_key] print('The key "' + some_key + '" was found, and its value is "' + some_value + '".') except KeyError: print('The key "' + some_key + '" was not found.') This method of checking for a key in a Python dictionary should generally be used as a fallback when other methods are not suitable. This is because exception handling in Python tends to be relatively slow, which can reduce program performance. Nonetheless, checking a key via try/except is a valid approach when needed. Using a for Loop In programs with more complex logic, explicit key searches in a dictionary might be required—especially if the search is combined with modifying the values of the found keys. In such cases, you can manually iterate over the dictionary using a for loop: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'name' is_found = False # Variable to store the search status # Iterate through the dictionary for found_key in some_dict: if found_key == some_key: is_found = True some_dict[found_key] = 'Jim' # Modify the value of the found key if is_found: print('The key "' + some_key + '" was found, and its value is now "' + some_dict[some_key] + '".') else: print('The key "' + some_key + '" was not found.') In this example, all dictionary keys are sequentially iterated over, and the value of the found key is modified. This approach allows for implementing more complex logic, combining both key searches and value modifications. Using a while Loop In some cases, it might be useful to use a while loop instead of a for loop: some_dict = {'name': 'James', 'age': 35, 'occupation': 'Just a guy...'} some_key = 'occupation' is_found = False some_keys = list(some_dict) # Convert dictionary keys to a list i = 0 while i < len(some_keys): if some_keys[i] == some_key: is_found = True some_dict[some_key] = 'Jim' # Modify the value of the found key break i += 1 if is_found: print('The key "' + some_key + '" was found, and its value is now "' + some_dict[some_key] + '".') else: print('The key "' + some_key + '" was not found.') While the overall application logic does not change, the syntax differs from the for loop approach. Conclusion Before accessing a value in a dictionary, it is essential to ensure that the desired key exists in the dictionary. Otherwise, you may encounter an error, causing the program to crash. This check can be performed using several built-in methods: in operator dict.get() function try/except exception handling for and while loops Each specific scenario calls for a different method of checking. For the simplest cases, the in operator is typically used. When the application logic is more complex and requires additional actions, a for or while loop may be employed. If you want to build a web service using Python, you can rent a cloud server at competitive prices with Hostman.
09 January 2025 · 6 min to read
MySQL

Creating an SSH Tunnel for MySQL Remote Access

Maintaining a secure database environment is vital in today's digital age. It helps prevent breaches and ensure the confidentiality of your information. A highly effective process for enhancing MySQL connection security is by implementing an SSH tunnel for remote access. This approach establishes an encrypted tunnel between your device and the server, ensuring data remains secure. SSH Tunneling SSH tunneling, also referred to as SSH port forwarding, enables the secure transmission of data between networks. By establishing an encrypted SSH tunnel, data can be safely transferred without the risk of exposure to potential threats. It possesses several benefits: Security: Encrypts data, keeping it safe from being seen or intercepted by others. Bypassing Restrictions: Allows access to services and resources blocked by firewalls. Flexibility: Can handle all network traffic types, fitting many uses. Types of SSH Tunneling SSH tunneling is of three types: Local Port Forwarding: It lets you redirect a port from your local machine to a destination machine using a tunnel. This is the method used in our guide. For example: ssh -L 3307:localhost:3306 your_username@your_server_ip Remote Port Forwarding: It lets you redirect a port from a remote machine to your local machine. This is useful for accessing local services from a remote machine. For example: ssh -R 9090:localhost:80 your_username@your_server_ip Dynamic Port Forwarding: It lets you create a SOCKS proxy to dynamically forward traffic through an SSH tunnel. This is useful for secure web browsing or bypassing firewalls. For example: ssh -R 9090:localhost:80 your_username@your_server_ip Prerequisites Before beginning, ensure you have: SSH client (OpenSSH, or PuTTY for Windows) MySQL server info SSH into the MySQL host machine securely. Setting Up Remote Access Go through these essential steps to securely set up remote access to your MySQL server through SSH tunnel: Step 1: Facilitate Connectivity For remote access, tune it to listen on an external IP. This allows SQL access from localhost to all IPs. Here’s how to do it: Access MySQL Config File Using a text editor, access the config file. On Ubuntu, it's typically located at: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf If the file isn't in its expected place, search for it with: sudo find / -name mysqld.cnf Edit bind-address Inside the file, find bind-address line, which is set to 127.0.0.1 by default, limiting server to local connections: Change the address to allow connections from all IP addresses by setting it to 0.0.0.0. Save changes by pressing Ctrl+X, Y to confirm, and Enter to exit. Restart MySQL Restart service to apply the updated settings: sudo systemctl restart mysql Step 2: Adjust Firewall By default, 3306 is the standard port in MySQL. To permit remote access, ensure this port is opened in your firewall settings. Tailor these steps to your specific firewall service. Open Port via UFW On Ubuntu, UFW is a pre-installed firewall utility. To allow traffic on 3306: sudo ufw allow from remote_ip to any port 3306 Substitute remote_ip with actual IP. Open Port via Firewalld On Red Hat-based and Fedora systems, Firewalld is the primary firewall tool. To open port 3306 for traffic, run these commands: sudo firewall-cmd --zone=public --add-service=mysql --permanentsudo firewall-cmd --reload The first command permanently allows MySQL traffic, and the second reloads the firewall to make the changes. Step 3: Open Your SSH Client Fire up your go-to SSH client. Opt for PuTTY on Windows, or the terminal if using macOS or Linux. Using Terminal (Linux or macOS) Implement this command: ssh -L 3307:localhost:3306 your_username@your_server_ip 3307: It's the local port your computer will listen to. localhost: It's a MySQL server address used by the SSH. It's where the service runs on the machine you're connecting to. 3306: The remote port where the server listens for incoming connections. username@server_ip: Your SSH login details. When required, verify the server's fingerprint. Confirm it matches by typing "yes" and pressing Enter.  Once confirmed, enter your SSH password if asked and press Enter for tunneling. After the tunnel is up, all traffic destined to local port 3307 will be forwarded to the remote machine in a secure fashion. Using PuTTY (Windows) Windows users can use the below-given instructions to perform tunneling: Launch PuTTY. From the left menu, direct to Connection > SSH > Tunnels. Input 3307 for Source port and localhost:3306 for the Destination field. Then hit Add. Navigate back to Session menu, enter server’s IP address and start the session using the Open button. Step 4: Connect to MySQL After setting up the tunnel, seamlessly link to the server through: sudo mysql -h localhost -P 3307 -u your_mysql_user -p Step 5: Verify the Connection Log into server and check if you can run queries: Additional Safeguards for Enhanced Security To further enhance the MySQL remote access security, consider the following: Implement Robust Passwords and Authentication Ensure using strong, unique passwords for both servers accounts. Implement key-based SSH authentication for added security. Here's how to set up SSH key authentication: Generate an SSH key pair via: ssh-keygen -t rsa -b 4096 -C "[email protected]" Copy the public key to the server via: ssh-copy-id your_username@your_server_ip Regularly Update Your Software Ensure that your server, client, and all associated software are consistently updated with the latest security patches and enhancements. This practice safeguards your system against known vulnerabilities and potential threats. Supervise and Audit Access Consistently examine access logs on both your MySQL and SSH server. Watch for any unusual activities or unauthorized attempts to gain access. Set up logging for both services: Check the SSH logs via: sudo tail /var/log/auth.log Enable and check MySQL logs by adding the below-given lines in the configuration file: [mysqld]general_log = 1general_log_file = /var/log/mysql/mysql-general.log You can view the general query log via: sudo cat /var/log/mysql/mysql-general.log To continuously monitor the log file in real time, use: sudo tail -f /var/log/mysql/mysql-general.log Implement IP Whitelisting Limit access to your MySQL by applying IP whitelisting. It ensures that connections are permitted only from specified IP addresses, thereby enhancing security: sudo ufw allow from your_trusted_ip to any port 3306 Replace your_trusted_ip with the IP address you trust. Troubleshooting Issues Here are a few common problems and solutions: Unable to Connect: Check SSH configuration and firewall rules. Ensure the SSH tunnel is correctly established and the server is reachable. Port Already in Use: Change the local forwarding port from 3307 to another available port. Authentication Errors: Verify your server's credentials. Ensure that the correct user permissions are set. MySQL Server Not Listening on Correct IP: Double-check the MySQL bind-address configuration and ensure the server is listening on the correct IP. Conclusion By adhering to this guide, you'll securely connect to your MySQL database via an SSH tunnel. This method not only boosts security but also enhances remote database management efficiency.  Regularly check your SSH tunnel setup to ensure a stable, secure connection. This practice ensures your data stays protected, providing peace of mind for seamless database operations. Hostman provides pre-configured and ready-to-use cloud databases, including cloud MySQL.
27 December 2024 · 6 min to read
Redis

How to Cache Node.js Applications with Redis

Caching is the process of storing copies of files in a cache — a temporary storage that is much faster to access than other available storage methods in the system. When developing Node.js applications, caching becomes highly relevant because database queries can take significantly longer than fetching data from temporary storage. For example, there is no need to reload the HTML markup of a webpage for every user request to the server — this would add several (sometimes dozens of) milliseconds to the response time. Storing the page (or JSON data for rendering in a SPA application) is much more efficient in the cache. In simple terms, caching is about optimization. This article will explore how to cache application data in a Node.js application using Redis with the Express framework. What is Redis? Redis (Remote Dictionary Server) is an open-source, in-memory database with simple "key-value" data structures. The terminology may vary. Some refer to Redis as a database, others as a caching tool, or something else. The key point is that Redis stores data in RAM instead of a hard drive, which results in higher performance. This is why Redis is referred to as an "in-memory" database. Although the data is kept in RAM, it is periodically saved to a hard drive in the form of snapshots. Redis is often used together with relational DBMSs, such as managed PostgreSQL. Installing Redis Server The installation process for Redis differs depending on the operating system, and you can find detailed instructions for each system on the official website. This article focuses on Ubuntu or Debian. Therefore, we will install the latest version of Redis from the official APT (Advanced Packaging Tool) repository — packages.redis.io: sudo apt update sudo apt install redis Once this is done, the Redis server is ready to use.  For Windows, you need to download the installer from the official GitHub repository. After installation, start the Redis server with the following CLI command: redis-cli For macOS, you can install Redis using the Homebrew package manager: brew install redis Once installed, start the server with: redis-server Node.js Project Configuration Before we dive into how to interact with Redis through a Node.js application, let's first create a separate working directory and navigate to it: mkdir node_redis cd node_redis As usual, let's create a package.json configuration file with a minimal set of data: { "name": "node_redis", "version": "1.0.0", "description": "Simple example of using Redis by Hostman", "main": "index.js", "license": "MIT", "dependencies": { "express": "latest", "axios": "latest", "redis": "latest" } } Note the specified dependencies. For this project, we will need the latest versions of the Express framework and the official Redis client for Node.js from NPM. This is a separate library that provides a high-level API (classes and functions) for interacting with a Redis server. The Axios module will help parse the JSON data the remote server will return in response to API requests. To install these dependencies, we will use the NPM package manager. If you don't have it yet, install it with the following command: sudo apt install npm You can read a separate guide on how to install the latest version of Node.js on Ubuntu. Since the app will use the async/await syntax, the minimum required version of Node.js is 8. Now, once all dependencies are specified, they can be installed: npm install Express Application Without Caching In this example, the application will use a fake API from JSONPlaceholder, specifically created for such purposes. We will send a request to the URL https://jsonplaceholder.typicode.com/posts/1 and receive mock data in JSON format: { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto" } Subsequent loading of data from the cache (instead of making repeated requests to the remote server) will increase the speed of the application. However, we will first implement the process of handling user requests without caching and add it later. Let's first create and edit our index.js file. The script will use modern JavaScript (ES6) syntax with async/await operators whenever possible: const express = require("express"); // import the Express framework const axios = require("axios"); // import the Axios module for working with JSON data const app = express(); // create an instance of the app // create an async function to request data from the remote server using axios async function getRemoteData() { const information = await axios.get(`https://jsonplaceholder.typicode.com/posts/1`); // send a request to the remote API console.log("There was a request to a remote server"); // log the informational message to the console return information.data; // return the raw JSON data } // create an async function to handle user requests async function onRequest(req, res) { let results = await getRemoteData(); // call the previously created function to get data from the remote server if(results.length === 0) throw "API error"; // handle empty responses with an error res.send(results); // respond to the user's request with the raw JSON data } app.get('/', onRequest); // attach the previously created function to the GET request hook app.listen(8080); // start listening for incoming requests on the default HTTP server port Now, you can run the script, open localhost in your browser, and see the raw JSON data displayed on the web page: node index.js Each request to the local server will, in turn, trigger a request to the remote server. For example, if you refresh the page three times in the browser, the message "There was a request to a remote server" will be printed three times in the terminal of the running Node.js server. But why? From a rational perspective, this is unnecessary. The data retrieved the first time should be cached to reduce the number of operations and user wait times. This is relevant only when the data is expected to remain static for a certain period — in other words, you can only cache data that doesn't change frequently. Express Application with Caching Let's modify the previous example so our application "learns" to cache data. To do this, we'll first connect the Redis client — add a new line at the beginning of the index.js: const redis = require("redis");  Now, naturally, we need to connect to the Redis server we started earlier, and only after that can we set and get keys. Let's add a few more lines of code: (async () => { client = redis.createClient(); client.on("error", (error) => console.log('Something went wrong', error)); // set up an error handler for Redis connection issues await client.connect(); // connect to the Redis server })(); Note that the connection to the Redis server is done in an anonymous self-invoking asynchronous function. This ensures that all pre-configuration steps are executed sequentially. Additionally, the connect function returns a promise, which can be handled using then/catch or inside an async function. In our example, the caching logic will be as follows: if the API request to the remote server is made for the first time, we cache the obtained data. If the data has been previously retrieved, it will be available in the cache — we fetch it and send it to the user. Let's modify the onRequest function (middleware) to implement caching: async function onRequest(req, res) { let results; // declare the variable for the result const cacheData = await client.get("post"); // try to get the "post" key from Redis database if (cacheData) { results = JSON.parse(cacheData); // parse the data from a raw string format into a structure } else { results = await getRemoteData(); // call the function to get data from the remote server if (results.length === 0) throw "API error"; // handle empty result with an error await client.set("post", JSON.stringify(results)); // cache the obtained data } res.send(results); // respond to the request with JSON data } Notice that the get function returns null if no value is saved for the given key in Redis. If this happens, an API request is made to the remote server. If data exists in the cache, it is retrieved and sent to the user. The set function is responsible for caching — it stores the given value under a specified key so we can retrieve it later with get. The full code of the application at this stage looks like this: const express = require("express"); // import Express framework const axios = require("axios"); // import Axios module for working with JSON data const redis = require("redis"); // import Redis client const app = express(); // create an instance of the application // Connect to Redis server (async () => { client = redis.createClient(); client.on("error", (error) => console.log('Something went wrong', error)); // set up an error handler for Redis connection issues await client.connect(); // connect to the Redis server })(); // create an asynchronous function to request data from the remote server using axios async function getRemoteData() { const information = await axios.get(`https://jsonplaceholder.typicode.com/posts/1`); // send a request to the remote server with the API console.log("There was a request to a remote server"); // log an informational message to the console return information.data; // return the obtained JSON data in raw form } // create an asynchronous function to handle user requests async function onRequest(req, res) { let results; // declare the variable for the result const cacheData = await client.get("post"); // attempt to retrieve the "post" variable from the Redis database if (cacheData) { results = JSON.parse(cacheData); // parse the data from a raw string into a structured format } else { results = await getRemoteData(); // call the function to fetch data from the remote server if (results.length === 0) throw "API error"; // handle empty result with an error await client.set("post", JSON.stringify(results)); // cache the obtained data } res.send(results); // respond with the JSON data } // run the HTTP server with the necessary configurations app.get('/', onRequest); // associate the created function with the GET request hook app.listen(8080); // start handling incoming requests on the standard HTTP server port Setting Cache Expiration We should periodically update the data stored in the cache to prevent it from becoming outdated. In real-world projects, APIs often provide additional information about how frequently cached data should be updated. This information is used to set a timeout — the duration for which the data in the cache remains valid. Once this time expires, the application makes a new request to obtain fresh data. In our case, we will take a simpler approach that is commonly used in practice. We will set a constant cache expiration time of 60 seconds. After this period, the application will make another request to the remote server for fresh data. It’s important to note that cache expiration is handled by Redis. This can be achieved by providing additional parameters when using the set function. To implement this, we will modify the set function call to include an additional structure as the third argument. Thus, the line: await client.set("post", JSON.stringify(results)); // cache the received data Will be updated to: await client.set("post", JSON.stringify(results), { EX: 60, NX: true }); // cache the received data with expiration In this case, we updated the previous line of code by adding the EX parameter, which is the cache expiration time in seconds. The NX parameter ensures that the key is only set if it does not already exist in the Redis database. This last parameter is important because re-setting the key would update the cache timeout without it, preventing it from fully expiring. Now, the Redis database will store the value of the post key for 60 seconds and then delete it. This means that every minute, the cacheData variable in our app will receive a null value, triggering an API request to the remote server and re-caching the obtained result. Conclusion This article demonstrated how in-memory storage can serve as a "mediator" between processing and storing data on solid-state drives. All of this is a form of caching that reduces unnecessary computational (and network) operations, thereby improving the application's performance and reducing the server's load. As shown, you can quickly set up such storage using Redis with a Node.js client. In our case, we used a mock API that returned trivial JSON data. In one scenario, the data was requested every time, while in the other, it was cached — sometimes with an expiration time. The examples provided are just the basics. As always, you can find more information on using Redis in the official documentation. The same applies to the documentation for Express and Axios.
26 December 2024 · 11 min to read

Powerful cloud DBMS —
for all your tasks of all kinds

Answers to Your Questions

What is PostgreSQL in the context of your cloud service, and how does it differ from other database solutions?

PostgreSQL is one of the most popular databases in the world, due to its open source code and wide community support. It is considered a "combine" that is suitable for both small projects and highly loaded systems.

PostgreSQL also works well in the cloud — on Hostman's advanced hardware.

How can I set up and start using PostgreSQL on your cloud platform?

Run your cloud DBMS directly from the Hostman control panel. You won't need to invest in server infrastructure or hire specialists. You can create and configure the database yourself, and Hostman specialists will help you with data migration.

Which versions of PostgreSQL are supported, and do you have plans for future updates?

We support the most widely used and stable versions of PostgreSQL 13, 14, 15 and 16.

What are the performance characteristics of PostgreSQL on your cloud service, including allocated resources and query speed?

Our PostgreSQL databases (all other DBMSs too) run only on the most high-performance server hardware: Intel and AMD processors of the latest generations and ultra-fast NVMe disks. Data exchange speed — from 100 to 200 Mbit/sec. In a private network — 1 Gbit.

How is the security of PostgreSQL ensured, and what encryption and authentication measures are in place?

First, we provide 99.9% SLA reliability and place servers exclusively in the most reliable Tier IV data centers that meet all international security standards:

  • ISO: standards for data center design,
  • PCI DSS: payment data processing standards,
  • GDPR: European Union standards for personal data protection.

Secondly, like all Hostman cloud solutions, databases are protected from unauthorized access — only your authorized employees and specialists can work with them. User management takes place directly in the modern Hostman control panel — no additional web interfaces are needed.

In addition, PostgreSQL itself has a built-in MVCC parallel access control system. Each user receives a snapshot — a "snapshot" of the database, in which changes are made. Only after the transaction is committed, they are transferred to the original database. While a person makes changes, they are not visible to other users.

What tools are available for managing PostgreSQL databases on your platform?

You can use any familiar web interfaces for database management by Adminer. But it is most convenient to do it directly in the Hostman control panel.

In the Hostman control panel you can:

- monitor load and resource consumption schedules,

- add users and manage their access rights,

- customize editing parameters,

- connect extensions and increase the functionality of the database,

- create backups, manage IP addresses, change tariffs and so on.

Can I scale resources for my PostgreSQL database, and what scaling options are provided?

Hostman will provide your project with the resources it needs — easily add power and capacity to your cloud database, right in your control panel. The Hostman support team can help you reduce resources.

How does your cloud service handle backup and recovery for PostgreSQL databases?

You can create database backups directly in the Hostman control panel: manually at any time or enable automatic backups once a day, once a week or once a month.

How does your support team assist with PostgreSQL-related issues and troubleshooting?

Hostman's fast, professional, and friendly support is always on call. We respond in just a few minutes and immediately start resolving your issues — no tedious line waits, escalations, or support tiers. You can reach us anytime via live chat, email, or even WhatsApp, with our specialists available 24/7 to assist you.

Do you have questions,
comments, or concerns?

Our professionals are available to assist you at any moment,
whether you need help or are just unsure of where to start.
Email us
Hostman's Support