Take the 2-minute tour ×

It seems like there should be a simpler way than:

import string
s = "string. With. Punctuation?" # Sample string 
out = s.translate(string.maketrans("",""), string.punctuation)

Is there?

share|improve this question
Seems pretty straightforward to me. Why do you want to change it? If you want it easier just wrap what you just wrote in a function. –  Hannes Ovrén Nov 5 '08 at 17:38
Well, it just seemed kind of hackish to be be using kind of a side effect of str.translate to be doing the work. I was thinking there might be something more like str.strip(chars) that worked on the entire string instead of just the boundaries that I had missed. –  Lawrence Johnston Nov 5 '08 at 18:00
Depends on the data too. Using this on data where there are server names with underscores as part of the name (pretty common some places) could be bad. Just be sure that you know the data and what it conatains or you could end up with a subset of the clbuttic problem. –  EBGreen Nov 5 '08 at 18:10
Depends also on what you call punctuation. "The temperature in the O'Reilly & Arbuthnot-Smythe server's main rack is 40.5 degrees." contains exactly ONE punctuation character, the second "." –  John Machin Mar 8 '10 at 21:49
I'm surprised no one mentioned that string.punctuation doesn't include non-English punctuation at all. I'm thinking about 。，！？：×“”〟, and so on. –  Clément Jan 3 '13 at 15:40
add comment

11 Answers

up vote 200 down vote accepted

From an efficiency perspective, you're not going to beat translate() - it's performing raw string operations in C with a lookup table - there's not much that will beat that bar writing your own C code. If speed isn't a worry, another option though is:

exclude = set(string.punctuation)
s = ''.join(ch for ch in s if ch not in exclude)

This is faster than s.replace with each char, but won't perform as well as non-pure python approaches such as regexes or string.translate, as you can see from the below timings. For this type of problem, doing it at as low a level as possible pays off.

Timing code:

import re, string, timeit

s = "string. With. Punctuation"
exclude = set(string.punctuation)
table = string.maketrans("","")
regex = re.compile('[%s]' % re.escape(string.punctuation))

def test_set(s):
    return ''.join(ch for ch in s if ch not in exclude)

def test_re(s):  # From Vinko's solution, with fix.
    return regex.sub('', s)

def test_trans(s):
    return s.translate(table, string.punctuation)

def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
    return s

print "sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000)
print "regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000)
print "translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000)
print "replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000)

This gives the following results:

sets      : 19.8566138744
regex     : 6.86155414581
translate : 2.12455511093
replace   : 28.4436721802
share|improve this answer
Thanks for the timing info, I was thinking about doing something like that myself, but yours is better written than anything I would have done and now I can use it as a template for any future timing code I want to write:). –  Lawrence Johnston Nov 5 '08 at 19:57
Great answer, thanks. –  Ali Afshar Nov 5 '08 at 20:04
Great answer. You can simplify it by removing the table. The docs say: "set the table argument to None for translations that only delete characters" (docs.python.org/library/stdtypes.html#str.translate) –  Alexandros Marinos Jul 1 '11 at 21:24
Using a list comprehension for the ''.join() would make it a little faster, but not fast enough to beat the regex or translate. See list comprehension without [ ], Python for why that is so. –  Martijn Pieters Nov 8 '13 at 12:13
add comment
myString.translate(None, string.punctuation)
share|improve this answer
ah, I tried this but it doesn't work in all cases. myString.translate(string.maketrans("",""), string.punctuation) works fine. –  Aidan Kane Aug 12 '10 at 12:30
When does it not work? –  Brandon Thomson Jan 11 '11 at 19:12
Note that for str in Python 3, and unicode in Python 2, the deletechars argument is not supported. –  agf Apr 14 '12 at 0:36
@agf: you still can use .translate() to remove punctuation even in Unicode and py3k cases using dictionary argument. –  J.F. Sebastian Aug 28 '12 at 7:53
add comment

I usually use something like this:

>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
...     s= s.replace(c,"")
>>> s
'string With Punctuation'
share|improve this answer
An uglified one-liner: reduce(lambda s,c: s.replace(c, ''), string.punctuation, s). –  J.F. Sebastian Aug 11 '12 at 12:03
add comment

Not necessarily simpler, but a different way, if you are more familiar with the re family.

import re, string
out = re.sub('[%s]' % re.escape(string.punctuation), '', s)
share|improve this answer
Works because string.punctuation has the sequence ,-. in proper, ascending, no-gaps, ASCII order. While Python has this right, when you try to use a subset of string.punctuation, it can be a show-stopper because of the surprise "-". –  S.Lott Nov 5 '08 at 17:49
Actually, its still wrong. The sequence "\]" gets treated as an escape (coincidentally not closing the ] so bypassing another failure), but leaves \ unescaped. You should use re.escape(string.punctuation) to prevent this. –  Brian Nov 5 '08 at 18:15
Yes, I omitted it because it worked for the example to keep things simple, but you are right that it should be incorporated. –  Vinko Vrsalovic Nov 5 '08 at 23:21
add comment

string.punctuation is ascii ONLY! A more correct (but also much slower) way is to use the unicodedata module:

# -*- coding: utf-8 -*-
from unicodedata import category
s = u'String — with -  «punctation »...'
s = ''.join(ch for ch in s if category(ch)[0] != 'P')
print 'stripped', s
share|improve this answer
You could: regex.sub(ur"\p{P}+", "", text) –  J.F. Sebastian Aug 11 '12 at 12:07
add comment

Regular expressions are simple enough, if you know them.

import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]','',s)
share|improve this answer
Great.. Can you explain? –  Outlier Apr 29 at 5:40
add comment

This might not be the best solution however this is how I did it.

import string
f = lambda x: ''.join([i for i in x if i not in string.punctuation])
share|improve this answer
add comment

For Python 3 str or Python 2 unicode values, str.translate() only takes a dictionary; codepoints (integers) are looked up in that mapping and anything mapped to None is removed.

To remove punctuation then, use:

import string

remove_punct_map = dict.fromkeys(map(ord, string.punctuation))

The dict.fromkeys() class method makes it trivial to create the mapping, setting all values to None based on the sequence of keys.

share|improve this answer
add comment

Your method doesn't work in Python 3, as the translate method doesn't accept the second argument any more. For a py3k solution, try this answer:

import unicodedata
import sys

tbl = dict.fromkeys(i for i in range(sys.maxunicode)
def remove_punctuation(text):
    return text.translate(tbl)
share|improve this answer
A simpler way to do it is to use the third argument to make trans such that: out = s.translate(string.maketrans("",""), string.punctuation) becomes: out = s.translate(str.maketrans("","", string.punctuation)) –  swhitman Apr 25 at 0:46
add comment

Do search and replace using the regex functions, as seen here.. If you have to repeatedly perform the operation, you can keep a compiled copy of the regex pattern (your punctuation) around, which will speed things up a bit.

share|improve this answer
Is string.punctuation locale corrected? If so, this might not be the best solution. –  EBGreen Nov 5 '08 at 17:46
I'm not sure, I haven't used it. I'm assuming that the poster/reader will know what punctuation they are replacing. –  Dana the Sane Nov 5 '08 at 18:02
Ehh...I don't know either. I would expect .punctuation to be locale corrected, but I wouldn't rely on it. You are probably right that if the user has a specific set of characters, then a compiled regex would be a good way to go. –  EBGreen Nov 5 '08 at 18:07
add comment

I like to use a function like this:

def scrub(abc):
    while abc[-1] is in list(string.punctuation):
    while abc[0] is in list(string.punctuation):
    return abc
share|improve this answer
add comment

Your Answer


