Python字典密钥丢失

时间:2010-06-05 12:48:21

标签: python parsing dictionary list

我以为我会整理一个快速脚本来整合我在多个CSS文件中分发的CSS规则,然后我可以缩小它。

我是Python的新手,但认为这是尝试新语言的一个很好的练习。我的主循环没有像我想的那样解析CSS。

我使用从CSS文件解析的选择器填充列表,以便按顺序返回CSS规则。稍后在脚本中,列表包含在字典中找不到的元素。

    for line in self.file.readlines():
      if self.hasSelector(line):
        selector = self.getSelector(line)
        if selector not in self.order:
          self.order.append(selector)
      elif selector and self.hasProperty(line):
        # rules.setdefault(selector,[]).append(self.getProperty(line))
        property = self.getProperty(line)
        properties = [] if selector not in rules else rules[selector]
        if property not in properties:
          properties.append(property)
        rules[selector] = properties
        # print "%s :: %s" % (selector, "".join(rules[selector]))
    return rules

遇到错误:

$ css-combine combined.css test1.css test2.css 
Traceback (most recent call last):
  File "css-combine", line 108, in <module>
    c.run(outfile, stylesheets)
  File "css-combine", line 64, in run
    [(selector, rules[selector]) for selector in parser.order],
KeyError: 'p'

交换输入:

$ css-combine combined.css test2.css test1.css 
Traceback (most recent call last):
  File "css-combine", line 108, in <module>
    c.run(outfile, stylesheets)
  File "css-combine", line 64, in run
    [(selector, rules[selector]) for selector in parser.order],
KeyError: '#header_.title'

我在代码中做了一些古怪的事情,比如字典键名中的下划线的子空格,如果它是一个问题 - 也许这是一个良性的预防措施?根据输入的顺序,在字典中找不到不同的密钥。

剧本:

#!/usr/bin/env python

import optparse
import re

class CssParser:

  def __init__(self):
    self.file = False
    self.order = [] # store rules assignment order

  def parse(self, rules = {}):
    if self.file == False:
      raise IOError("No file to parse")

    selector = False
    for line in self.file.readlines():
      if self.hasSelector(line):
        selector = self.getSelector(line)
        if selector not in self.order:
          self.order.append(selector)
      elif selector and self.hasProperty(line):
        # rules.setdefault(selector,[]).append(self.getProperty(line))
        property = self.getProperty(line)
        properties = [] if selector not in rules else rules[selector]
        if property not in properties:
          properties.append(property)
        rules[selector] = properties
        # print "%s :: %s" % (selector, "".join(rules[selector]))
    return rules

  def hasSelector(self, line):
    return True if re.search("^([#a-z,\.:\s]+){", line) else False

  def getSelector(self, line):
    s = re.search("^([#a-z,:\.\s]+){", line).group(1)
    return "_".join(s.strip().split())

  def hasProperty(self, line):
    return True if re.search("^\s?[a-z-]+:[^;]+;", line) else False

  def getProperty(self, line):
    return re.search("([a-z-]+:[^;]+;)", line).group(1)


class Consolidator:
  """Class to consolidate CSS rule attributes"""

  def run(self, outfile, files):
    parser = CssParser()
    rules = {}
    for file in files:
      try:
        parser.file = open(file)
        rules = parser.parse(rules)
      except IOError:
        print "Cannot read file: " + file
      finally:
        parser.file.close()

    self.serialize(
      [(selector, rules[selector]) for selector in parser.order],
      outfile
    )

  def serialize(self, rules, outfile):
    try:
      f = open(outfile, "w")
      for rule in rules:
        f.write(
          "%s {\n\t%s\n}\n\n" % (
            " ".join(rule[0].split("_")), "\n\t".join(rule[1])
          )
        )
    except IOError:
      print "Cannot write output to: " + outfile
    finally:
      f.close()

def init():
  op = optparse.OptionParser(
    usage="Usage: %prog [options] <output file> <stylesheet1> " +
      "<stylesheet2> ... <stylesheetN>",
    description="Combine CSS rules spread across multiple " +
      "stylesheets into a single file"
  )
  opts, args = op.parse_args()
  if len(args) < 3:
    if len(args) == 1:
      print "Error: No input files specified.\n"
    elif len(args) == 2:
      print "Error: One input file specified, nothing to combine.\n"
    op.print_help();
    exit(-1)

  return [opts, args]

if __name__ == '__main__':
  opts, args = init()
  outfile, stylesheets = [args[0], args[1:]]
  c = Consolidator()
  c.run(outfile, stylesheets)

测试CSS文件1:

body {
    background-color: #e7e7e7;
}

p {
    margin: 1em 0em;    
}

文件2:

body {
    font-size: 16px;
}

#header .title {
    font-family: Tahoma, Geneva, sans-serif;
    font-size: 1.9em;
}

#header .title a, #header .title a:hover {
    color: #f5f5f5;
    border-bottom: none;
    text-shadow: 2px 2px 3px rgba(0, 0, 0, 1);
}

提前致谢。

1 个答案:

答案 0 :(得分:3)

更改

def hasProperty(self, line):
    return True if re.search("^\s?[a-z-]+:[^;]+;", line) else False

def hasProperty(self, line):
    return True if re.search("^\s*[a-z-]+:[^;]+;", line) else False

hasProperty未匹配任何内容,因为\s?仅匹配0或1个空白字符。