How to replace spaces with underscores in Python

Learn how to replace spaces with underscores in Python. Discover multiple methods, real-world applications, and tips for debugging common errors.

How to replace spaces with underscores in Python
Published on: 
Wed
Mar 25, 2026
Updated on: 
Fri
Mar 27, 2026
The Replit Team

You often need to replace spaces with underscores in Python. This common string task ensures file names, URLs, and variables are compatible and readable across different systems.

In this article, you'll learn several techniques to substitute spaces, like the replace() method. You'll also find practical tips, real-world applications, and advice to debug common errors.

Using the replace() method

text = "Hello World Python Programming"
new_text = text.replace(" ", "_")
print(new_text)--OUTPUT--Hello_World_Python_Programming

The replace() method is Python's most direct tool for this job. It's a built-in string function that returns a new string with all specified occurrences of a substring replaced. In this case, text.replace(" ", "_") finds every space and substitutes it with an underscore.

It's crucial to remember that strings in Python are immutable, meaning they can't be changed. The replace() method doesn't alter the original text variable. Instead, it creates a new string that you must assign to a new variable, like new_text, to use it.

Basic replacement techniques

Beyond the simple replace() method, Python provides more versatile tools such as translate(), re.sub(), and list comprehensions with join() for handling various scenarios.

Using string translate() method

text = "Python is fun to learn"
translation_table = str.maketrans({" ": "_"})
new_text = text.translate(translation_table)
print(new_text)--OUTPUT--Python_is_fun_to_learn

The translate() method is a highly efficient way to substitute characters. It works in two steps. First, you create a translation table with str.maketrans(), which defines how characters should be mapped. Here, it maps each space " " to an underscore _.

  • Next, the translate() method applies this table to the string, performing all substitutions in one go.
  • While it looks more complex for a single replacement, this method shines when you need to swap multiple different characters simultaneously, making your code cleaner and faster.

Using regular expressions with re.sub()

import re
text = "Replace all spaces in this text"
new_text = re.sub(r'\s', '_', text)
print(new_text)--OUTPUT--Replace_all_spaces_in_this_text

For more complex substitutions, you can use the re.sub() function from Python's regular expression module. This function finds all substrings where a pattern matches and replaces them with a different string.

  • The pattern r'\s' is a regular expression that matches any whitespace character—not just spaces but also tabs and newlines.
  • This makes re.sub() more versatile than replace(), as it can handle various types of spacing in one go. You simply provide the pattern, the replacement string ('_'), and the text to modify.

Using list comprehension and join()

text = "Python string manipulation example"
new_text = ''.join(['_' if char == ' ' else char for char in text])
print(new_text)--OUTPUT--Python_string_manipulation_example

This approach gives you precise control by combining a list comprehension with the join() method. It works by first building a new list of characters from the original string.

  • The list comprehension iterates through the text, using a conditional expression to replace each space with an underscore while leaving other characters untouched.
  • Finally, the join() method stitches all the characters from the new list back together into a single string.

Advanced techniques and optimizations

When you need more flexibility than the standard methods provide, you can turn to functional programming or build custom functions for complex replacements.

Using functional programming with map()

text = "Functional approach to string replacement"
new_text = ''.join(map(lambda char: '_' if char == ' ' else char, text))
print(new_text)--OUTPUT--Functional_approach_to_string_replacement

This method offers a functional programming twist by using the map() function. It applies a simple operation—defined by a lambda function—to every character in the string without needing an explicit loop.

  • The lambda function is a concise, one-line function that checks each character. If it's a space, it returns an underscore; otherwise, it returns the original character.
  • Finally, ''.join() stitches the characters processed by map() back into a single, complete string. This approach is conceptually similar to a list comprehension but aligns more closely with a functional style.

Creating a custom replacement function

def replace_spaces(text, replacement='_'):
   return text.replace(' ', replacement)

text = "Customize your replacement character"
print(replace_spaces(text))
print(replace_spaces(text, '-'))--OUTPUT--Customize_your_replacement_character
Customize-your-replacement-character

Wrapping the replacement logic in a custom function like replace_spaces makes your code more reusable and readable. This function encapsulates the replace() method and adds flexibility through an optional parameter.

  • The replacement parameter defaults to an underscore, so you don't have to specify it every time.
  • You can also pass a different character, such as a hyphen, making the function adaptable for various needs without rewriting code.

Handling multiple replacements simultaneously

def replace_multiple(text, replacements):
   for old, new in replacements.items():
       text = text.replace(old, new)
   return text

text = "Spaces and tabs need replacing"
print(replace_multiple(text, {' ': '_', 'a': '@'}))--OUTPUT--Sp@ces_@nd_t@bs_need_repl@cing

When you need to swap several different characters at once, a custom function like replace_multiple offers a clean solution. It accepts a dictionary of replacements, where each key is the character to find and its value is the new character.

  • The function loops through the replacements dictionary using the .items() method.
  • In each iteration, it calls the standard replace() method, updating the text with the new substitution. This process repeats until all specified replacements are complete.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the string replacement techniques we've explored, such as using replace() or re.sub(), Replit Agent can turn them into production-ready tools.

  • Build a URL slug generator that converts article titles into clean, web-friendly links.
  • Create a file renaming utility that automatically replaces spaces with underscores for better script compatibility.
  • Deploy a code formatter that converts descriptive text into valid variable or function names.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser.

Common errors and challenges

Even simple string replacements can trip you up, but these common pitfalls are easy to sidestep with a little foresight.

Forgetting that replace() doesn't modify the original string

A frequent mistake is calling replace() and expecting the original string to change. Since strings are immutable in Python, this method can't alter them directly—it always returns a new, modified string.

If you don't assign this new string to a variable, the result is lost, and your original text remains unchanged. Always remember to capture the output, like new_text = text.replace(' ', '_').

Dealing with case sensitivity in replacements

The replace() method is case-sensitive, which can lead to incomplete substitutions if you're not careful. For example, calling text.replace('python', 'code') won't affect "Python" with a capital "P".

To ensure all instances are replaced regardless of case, you can convert the string to a consistent case first. A common approach is to use the lower() method before replacing, like text.lower().replace(' ', '_').

Watch out for replacement order when using multiple replace() calls

When you chain multiple replace() calls, the order matters significantly. Each call operates on the result of the previous one, which can cause unexpected outcomes.

  • For instance, imagine you want to swap spaces for underscores and underscores for hyphens.
  • If you run text.replace(' ', '_').replace('_', '-'), all original spaces will ultimately become hyphens because the second call also affects the newly created underscores.
  • To avoid this, plan your replacement sequence carefully or use a method that handles simultaneous replacements, like the custom function shown earlier.

Forgetting that replace() doesn't modify the original string

It's a common oversight to call replace() and find your original string unchanged. This happens because the method returns a new string instead of modifying the original one. The following code demonstrates what happens when you forget to capture this result.

text = "Hello World"
text.replace(" ", "_")
print(text)  # Still prints "Hello World"

The line text.replace(" ", "_") executes, but the new string it generates is immediately lost. Consequently, print(text) displays the original, unchanged variable. The following example shows the correct approach to capture the result.

text = "Hello World"
text = text.replace(" ", "_")
print(text)  # Now prints "Hello_World"

By reassigning the output of replace() back to the text variable, you're correctly updating it with the modified string. This is the key to working with immutable types like strings. Be especially mindful of this when chaining methods or passing strings into functions, as it's easy to lose track of which version of the string your code is actually using. Always ensure your next operation uses the newly returned string.

Dealing with case sensitivity in replacements

The replace() method is case-sensitive, which means it won't catch every variation of a word if the capitalization differs. This can leave your string only partially modified, leading to subtle bugs. The following code demonstrates what happens when you overlook case differences.

text = "Python is Python is PYTHON"
text = text.replace("python", "Java")
print(text)  # Still contains all "Python" occurrences

The replace("python", "Java") call only targets the lowercase version of the word. It leaves the capitalized instances "Python" and "PYTHON" untouched, resulting in an incomplete replacement. The following code demonstrates a reliable fix for this issue.

text = "Python is Python is PYTHON"
text = text.replace("Python", "Java").replace("PYTHON", "JAVA")
print(text)

To solve this, you can chain multiple replace() calls. This approach lets you target each specific case one by one, ensuring all variations are replaced. The first call handles "Python", and the second addresses "PYTHON".

This method is effective when you know the exact capitalizations you need to address. It's particularly useful when cleaning up user input or data from inconsistent sources where capitalization can vary widely.

Watch out for replacement order when using multiple replace() calls

Chaining multiple replace() calls is tricky because the order matters. Each function call modifies the string returned by the previous one, creating a cascade of unexpected changes. The following code shows exactly how this can go wrong.

text = "ab"
text = text.replace("a", "b").replace("b", "c")
print(text)  # Prints "cc" instead of "bc"

The first replace() call turns "ab" into "bb". The second call then operates on that new string, changing both b characters to c. The following code demonstrates how to avoid this unintended chain reaction.

text = "ab"
replacements = [("a", "b"), ("b", "c")]
for old, new in replacements:
   text = text.replace(old, new)
print(text)  # Prints "bc"

This approach organizes your substitutions into a list of pairs, which makes your code more readable than long method chains. A for loop then iterates through each (old, new) tuple, applying the replace() method sequentially. It’s a cleaner structure, but you still need to watch the order. Each replacement operates on the result of the previous one, so plan your sequence carefully to avoid unintended cascading effects, especially when replacement characters overlap.

Real-world applications

Now that you can sidestep common errors, you can apply these replacement skills to creating URL-friendly slugs and converting between code conventions.

Creating URL-friendly slugs from article titles

To create a slug, you'll typically convert the title to lowercase, replace spaces with hyphens, and strip out any special characters that could cause issues in a URL.

def create_slug(title):
   slug = title.lower().replace(' ', '-')
   slug = ''.join(c for c in slug if c.isalnum() or c == '-')
   return slug

article_title = "10 Python Tips & Tricks for Beginners!"
print(create_slug(article_title))

This function first chains lower() and replace() for basic formatting. The core logic, however, lies in the generator expression that filters the string.

  • It iterates character by character, using the condition c.isalnum() or c == '-' to decide what to keep.
  • This check preserves only letters, numbers, and hyphens, effectively stripping out symbols like & or !.

Finally, the join() method assembles these approved characters into the final, clean slug.

Converting between snake_case and camelCase

Python's string manipulation skills are also essential for converting variable names between common conventions like snake_case and camelCase.

def snake_to_camel(snake_str):
   components = snake_str.split('_')
   return components[0] + ''.join(x.title() for x in components[1:])

def camel_to_snake(camel_str):
   return ''.join(['_'+c.lower() if c.isupper() else c for c in camel_str]).lstrip('_')

variable_name = "user_profile_data"
print(snake_to_camel(variable_name))
print(camel_to_snake("getUserProfile"))

These two functions offer a practical way to switch between coding conventions. The snake_to_camel function splits the string at each underscore using split('_'). It keeps the first word as is, then uses title() to capitalize every subsequent word before joining them into a single string.

  • Conversely, camel_to_snake uses a list comprehension to iterate through the string, inserting an underscore before each uppercase letter.
  • It also converts that letter to lowercase. The final lstrip('_') call is a neat trick. It removes any leading underscore if the input string started with a capital.

Get started with Replit

Turn your new skills into a real tool. Tell Replit Agent: “Build a file renamer that replaces spaces with underscores” or “Create a URL slug generator for blog titles.”

Replit Agent writes the code, tests for errors, and deploys your app. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.