IPRoyal
Back to blog

Running A Python Script As A Service in Windows, Linux & More

Marijus Narbutas

Last updated -

How to

In This Article

Ready to get started?

Register now

Running a Python script locally a single time is often a simple task. You can even do so through your IDE, which has a working piece of Python code. Usually, you just have to click a “play” button.

Turning your Python script into a service and running it on a different operating system or on the cloud is a bit of a different beast. Creating a service has a few distinct benefits, namely that the Python script can run continuously, be completely automated, and be scheduled.

Running a Python Script as a Service in Windows

You can turn any working piece of Python code into a Windows service, although you’ll need to make some modifications to your script. Primarily, wrapping your service around a specific library to turn it into a Windows service.

Let’s take a simple Python file that’ll open a file, run a few loops, and exit the loop later on:

import time
import traceback
import os

# Set the path to the log file in the specified directory
log_file_path = "C:\\Logs\\service_log.txt"

def log_message(message):
    """Logs a message to a text file."""
    with open(log_file_path, "a") as log_file:
        log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")

def main():
    try:
        # Log that the script has started
        log_message("Test script has started running.")
        
        # Main loop to simulate work
        for i in range(5):
            log_message(f"Loop iteration {i + 1}: Script is running...")
            time.sleep(2)  # Simulate work with a delay

        # Log completion of the work cycle
        log_message("Test script has completed a work cycle.")

    except Exception as e:
        # Log any exceptions that occur
        error_message = f"Exception in test script: {str(e)}\n{traceback.format_exc()}"
        log_message(error_message)

if __name__ == "__main__":
    main()

Before running the Python code, create a folder and a file with the appropriate name in the directory to ensure the script runs correctly. You could create both if none are available. However, we want to keep the process as simple as possible.

These types of Python code are great for testing your service logic as you get direct feedback on whether it’s working or not. If your code performs some tasks that are generally invisible, you won’t know that your Python scripts are running correctly unless you run some direct tests.

So, now’s the time to turn our Python script into a service. Let’s start by installing a library that’ll allow us to turn a Python script into a Windows service – pywin32:

pip install pywin32

The difficult part comes in creating a class that’ll manage our Windows service. Luckily, most Windows service wrappers follow the same logic, and plenty of code can be copy-pasted:

import win32serviceutil
import win32service
import win32event
import time
import traceback


class MyPythonService(win32serviceutil.ServiceFramework):
    _svc_name_ = "MyPythonService"
    _svc_display_name_ = "My Python Service"
    _svc_description_ = "Service that runs my Python script."

    log_file_path = "C:\\Logs\\service_log.txt"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.stop_event = win32event.CreateEvent(None, 0, 0, None)
        self.running = True

    def log_message(self, message):
        """Logs a message to a text file."""
        with open(self.log_file_path, "a") as log_file:
            log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")

    def SvcStop(self):
        # Update the service status to STOP_PENDING
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.stop_event)
        self.running = False
        # Log that the service is stopping
        self.log_message("MyPythonService is stopping.")

    def SvcDoRun(self):
        try:
            # Log that the service has started
            self.log_message("MyPythonService has started running.")

            # Main loop for the service
            while self.running:
                # Log an ongoing activity message
                self.log_message("MyPythonService is performing its task.")

                # Simulate some work with a delay and logging
                for i in range(5):
                    self.log_message(f"Loop iteration {i + 1}: Script is running...")
                    time.sleep(2)  # Simulate work with a delay

                # Log completion of work cycle
                self.log_message("MyPythonService has completed a work cycle.")

        except Exception as e:
            # Log the exception details
            error_message = f"Exception in MyPythonService: {str(e)}\n{traceback.format_exc()}"
            self.log_message(error_message)
            self.running = False  # Ensure the service stops if an error occurs


if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(MyPythonService)

We’ve now created a Windows service that’ll automatically run our Python script in the background. Yet, it can’t be run like a regular script, we’ll need to install it as a Windows service.

To do so, name your Python file something like “python_service.py” and open up the Command Prompt (Windows Terminal) as an Administrator.

Use the “cd” command line to go to your Python project folder. Then, type in:

python python_service.py install

You may get one of two errors. The operating system may state that “python” is an unrecognized command. You’ll have to get a new Python version , and, while installing, make sure to mark “add Python to PATH”.

Alternatively, you may get an error related to “pywin32”. If that is the case, run “pip install pywin32” within Command Prompt.

If everything happens correctly, you’ll get a success message stating that your Python service has been installed. Take note of the name (if you made any changes to the Python code above). Run the command:

net start MyPythonService

There should be a small delay, but the Windows Terminal should display another success message. Checking the folder and file you’ve created should show some logs.

Additionally, visiting the Windows Service Manager (accessible through the Windows button and typing in “Services”) should display a new one – MyPythonService.

It’s recommended to also stop the service by running the following command:

net stop MyPythonService

Finally, you can use the command line to remove the service as well:

python python_service.py remove

Running a Python Script as a Service in Linux

There are two main ways to run a Python as a service in Linux – you can simply start the script to run in the background or use a daemon. For the former, you’ll need a Python script that already functions like a service and you’ll need to start it each time you boot up the operating system.

To get started, you’ll need to modify the previously written code slightly. First, all Windows-based utilities should be removed as Linux has no support for them. So, it’s better to take the test Python script that has no service modules.

Additionally, our Python script used the Windows pathing and file name notation, which won’t work on Linux either. So, that also has to be modified:

import time
import traceback
import os

# Set the path to the log file
log_file_path = "/var/log/my_python_service.log"

def log_message(message):
    """Logs a message to a text file."""
    with open(log_file_path, "a") as log_file:
        log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")

def main():
    try:
        log_message("MyPythonService has started running.")
        
        while True:
            # Log a periodic activity message
            log_message("MyPythonService is performing its task.")
            
            # Simulate work with a delay and log progress
            for i in range(5):
                log_message(f"Loop iteration {i + 1}: Script is running...")
                time.sleep(2)  # Simulate work with a delay

            # Log the completion of a work cycle
            log_message("MyPythonService has completed a work cycle.")

    except Exception as e:
        # Log any exceptions that occur
        error_message = f"Exception in MyPythonService: {str(e)}\n{traceback.format_exc()}"
        log_message(error_message)

if __name__ == "__main__":
    main()

Make sure to create the file and folder – it’ll reduce troubleshooting as our main goal is running Python scripts as a service.

You can run the code by heading over to the folder where the Python script is stored through the command line and typing in:

python3 /path/to/script.py &

Our Python script, however, wouldn’t work as a service as it would run a single work cycle and exit. Running Python scripts as services in Linux is primarily performed by making a daemon.

Unlike in Windows, we don’t need to modify our Python script itself, rather a configuration file is created in systemd. Start by going to the following path:

cd /etc/systemd/system

Then, create the following configuration file. Depending on your distribution and version, you may have a GUI or have to use the command line (sudo nano or sudo vim commands):

[Unit]
Description=My Python Service
After=network.target

[Service]
ExecStart=/usr/bin/python3 /path/to/script.py
Restart=always
User=myuser
WorkingDirectory=/path/to/

[Install]
WantedBy=multi-user.target

Make sure to edit the text file to correctly point to your Python script path and name. Otherwise, you’ll get an error message.

Finally, you’ll need to reload systemd, enable, and start the service. Additionally, it’s still recommended to check the status of your service even if it started correctly:

sudo systemctl daemon-reload
sudo systemctl enable my_python_service
sudo systemctl start my_python_service
sudo systemctl status my_python_service

Running Python Scripts in Cloud Environments

Cloud environments will usually give you a small part of the server’s hardware. So, in essence, you’re dealing with virtual environments that run either Unix or Windows (most commonly).

If you already have such a server on AWS (or any other cloud provider), it’ll be mostly no different than running a service on your local machine. There may be some changes depending on the amount of access you get to the virtual environment, but otherwise, the process is the same.

Such methods are perfect if you want to run a service that somehow influences the local instance. There are plenty of other applications, however, such as web scraping.

Web scraping is the process of extracting data from a large number of web pages by sending a bot and downloading the HTML. The HTML is then processed to extract the valuable data from any number of web pages at once (or in sequence).

You often need to integrate proxies into the Python code , as the constant connection requests may look like a DDoS or spam attempt and get you banned.

Python is also a great option for web scraping due to the major community support. There’s plenty of tutorials, web scraping libraries , and lots of readily available code online.

Since web scraping mostly works by interacting with web pages, very few changes are done internally. These applications are great for Lambda (or similar) instances wherein no actual server is being rented out.

The serverless instance then requires you to upload the Python script (usually through the command line) and run it. You don’t get access to the server directly otherwise and only pay for compute time and bandwidth.

For a Lambda instance, however, you’d need to set up some external storage system such as S3 as you’d need to store the web scraping result file somewhere. Lambda instances only run computing, so it would perform web scraping and then delete the file once it’s completed – something you don’t want.

Conclusion

Running a Python script as a service is relatively easy. However, the implementation depends on the operating system. Linux can be done through systemd by creating a file, while Windows will need a wrapper (such as pywin32).

Local installations are great if you want to manipulate some settings or perform local actions. You can also run simple use cases such as web scraping, as long as the scale isn’t major.

Alternatively, if you want to perform tasks such as web scraping on a larger scale, you can also get a cloud environment and run the Python script externally. Using a serverless instance with external storage may be the best option for small-to-medium projects, however, you have to have a working Python file and be familiar with command line utilities.

Additionally, it’s recommended to test out your Python script internally first. You may be running into errors when web scraping and get no good results, but you’ll still have to pay for the bandwidth and compute time.

Create account

Author

Marijus Narbutas

Senior Software Engineer

With more than seven years of experience, Marijus has contributed to developing systems in various industries, including healthcare, finance, and logistics. As a backend programmer who specializes in PHP and MySQL, Marijus develops and maintains server-side applications and databases, ensuring our website works smoothly and securely, providing a seamless experience for our clients. In his free time, he enjoys gaming on his PS5 and stays active with sports like tricking, running, and weight lifting.

Learn More About Marijus Narbutas
Share on

Related articles