input: Write a python function to preprocess a given dataset of text for further processing by a machine learning model.
  assert preprocess_text('hello world! My name is John.')==['hello', 'world', 'name', 'john']
  assert preprocess_text('The quick brown fox jumps over the lazy dog.')==['quick', 'brown', 'fox', 'jump', 'lazy', 'dog']
  assert preprocess_text('Data science is the best!')==['data', 'science', 'best']
output: def preprocess_text(text):
      import re
      from nltk.corpus import stopwords
      from nltk.stem import PorterStemmer
  
      # Convert to lowercase
      text = text.lower()
      
      # Remove punctuation and non-alphabetic characters
      text = re.sub(r'[^a-z\s]', '', text)
      
      # Tokenize the text
      words = text.split()
      
      # Remove stopwords
      stop_words = set(stopwords.words('english'))
      words = [word for word in words if word not in stop_words]
      
      # Stem the words
      stemmer = PorterStemmer()
      words = [stemmer.stem(word) for word in words]
      
      return words