【问题标题】:Writing to text file is cut off写入文本文件被切断
【发布时间】:2017-03-23 08:50:54
【问题描述】:

我目前正在编写一些 Python 代码,以获取 JSON 文件的某些文本元素并将此文本以 'spell name': 'description' 格式写入文件。例如,采用以下 JSON 文件的名称和简短描述元素(为简洁而编辑):

[
    {
        "pk": 0,
        "model": "srd20.spell",
        "fields": {
            "description": "<p>An arrow of acid springs from your hand and speeds to its target. You must succeed on a <a href=\"../combat.html#_ranged-touch-spells-in-combat-95\">ranged touch attack</a> to hit your target. The arrow deals 2d4 points of acid damage with no splash damage. For every three caster levels you possess, the acid, unless neutralized, lasts for another round (to a maximum of 6 additional rounds at 18th level), dealing another 2d4 points of damage in each round.</p>",
            "school": "conjuration",
            "saving_throw": "none",
            "name": "Acid Arrow",
            "reference": "prd/spells",
            "level": "sorcerer/wizard 2",
            "spell_resistance": "no",
            "area": "",
            "casting_time": "1 standard action",
            "effect": "one arrow of acid",
            "descriptor": "acid",
            "range": "long (400 ft. + 40 ft./level)",
            "short_description": "Ranged touch attack; 2d4 damage for 1 round + 1 round/3 levels.",
            "components": "V, S, M (rhubarb leaf and an adder's stomach), F (a dart)",
            "altname": "acid-arrow",
            "duration": "1 round + 1 round per three levels",
            "subschool": "creation",
            "target": ""
        }
    },
...
]

并将这些详细信息写入文件,如下所示:

'Acid Arrow': 'Ranged touch attack; 2d4 damage for 1 round + 1 round/3 levels.',

到目前为止,我所拥有的似乎几乎可以解决问题。它采用 JSON,遍历每个元素(列表中的拼写)并将该拼写的名称和描述以我想要的格式写入文件 spelllistparsed.txt:

import json

fWrite = open('spelllistparsed.txt', 'w')

with open('spells.json') as data_file:
    data = json.load(data_file)

for count, item in enumerate(data, start=0):
    fWrite.write("'" + data[count]["fields"]["name"] + "': " + "'"
                 + data[count]["fields"]["short_description"] + "',\n")

但问题是当我运行程序时,它只会将列表的一部分写入新文件。当我运行它时,最终结果将显示应该存在的大约 30 个咒语。经过反复试验,我发现了以下几点:

  • 无论我使用哪种方法进行迭代,这似乎都会发生。我尝试过使用整数计数,for spell in data: 但它们会导致相同的结果。还尝试增加 2 - 每隔一个咒语就会被写入,但在大约 50 个左右的咒语后仍然会被切断。
  • 当我对法术使用不同的第二个字段(不是“short_description”,而是法术的不同元素,如“description”或“effect”)时,会向文件中写入不同数量的文本。对于短文本,所有 1000 个左右的 spell name : second field 都将显示,而对于第二个字段中的大量文本,它只会将几个拼写写入 spelllistparsed.txt。我认为写入文件的内容没有特定的字符限制,但这似乎是问题的一部分
  • 当我将第二个字段设置为始终打印相同的内容 (data[0]["fields"]["short_description"]) 时,它成功地将所有拼写作为 'spell name': 'description for spell 0' 写入文件,因此问题可能在于处理许多不同的描述
  • 据我所知 JSON 是有效的,这应该是可能的(通过 JSONLint 运行)
  • 在运行当前代码时,它会通过 Baleful Polymorph 写入法术 Acid Arrow

任何帮助将不胜感激!我觉得这应该相对简单,但这是我第一次使用 Python,到目前为止我寻找解决方案没有结果。让我知道我是否应该在此处包含任何其他可以提供帮助的信息。

咒语的 JSON 文件:https://github.com/machinalis/django-srd20/blob/master/pathfinder/spells.json

【问题讨论】:

    标签: python json python-2.7


    【解决方案1】:

    Python2 将 JSON 字符串加载为 unicode 对象,在将它们写入文件对象之前需要对其进行编码。您的脚本在第 31 项失败的原因是因为这显然是第一项包含非 ASCII 字符(在本例中为 U+2013 “-”)。

    你会希望你的代码看起来像这样:

    import json
    
    fWrite = open('spelllistparsed.txt', 'w')
    
    with open('spells.json') as data_file:
        data = json.load(data_file)
    
    # note that you do not need to use enumerate here as you never use the index
    for item in data:
        name = item["fields"]["name"].encode("utf-8")
        desc = item["fields"]["short_description"].encode("utf-8")
        fWrite.write("'" + name + "': " + "'" + desc + "',\n")
    
    # always close open files when you're done!
    fWrite.close()
    

    或者,您可以使用 Python3,在这种情况下,您只需将关键字参数 encoding='utf-8' 添加到脚本中对 open 的第一次调用中。而且您仍然希望在最后关闭文件。

    【讨论】:

    • 感谢您的帮助和解释——这解决了我的问题!
    【解决方案2】:

    您需要在文件末尾添加fWrite.close() 或使用与拼写文件相同的“with”上下文管理器。

    当 Python 存在时文件被关闭,但文件输出通常被缓冲,如果没有换行符,挂起的输出将不会被刷新到文件系统。

    【讨论】:

      【解决方案3】:

      您可以使用Python2 尝试此示例,它从给定的 URL 获取数据:

      from urllib2 import urlopen
      from json import loads
      # Fetching the data from this URL
      url = "https://raw.githubusercontent.com/machinalis/django-srd20/master/pathfinder/spells.json"
      
      def load_from_url(url = ""):
          data = urlopen(url)
          response = data.read()
          return loads(response.decode('utf-8'))
      
      
      def get_data(data = ""):
          # The output file is called new_data
          with open("new_data", "a") as f:
              for k in data:
                  f.write("'%s':'%s',\n" % (k["fields"]["name"].encode('utf-8'), k["fields"]["short_description"].encode('utf-8')))
      
      data = load_from_url(url)
      get_data(data)
      

      另外,你可以在Python3内完成任务:

      from urllib.request import urlopen
      from json import loads
      # Fetching the data from this URL
      url = "https://raw.githubusercontent.com/machinalis/django-srd20/master/pathfinder/spells.json"
      
      def load_from_url(url = ""):
          with urlopen(url) as data:
              response = data.read()
              return loads(response.decode('utf-8'))
      
      
      def get_data(data = ""):
          # New file is called new_data
          with open("new_data", "a") as f:
              for k in data:
                  f.write("'{0}':'{1}',\n".format(k["fields"]["name"], k["fields"]["short_description"]))
      
      data = load_from_url(url)
      get_data(data)
      

      输出(对于使用Python2和Python3的代码:

      'Acid Arrow':'Ranged touch attack; 2d4 damage for 1 round + 1 round/3 levels.',
      'Acid Fog':'Fog deals acid damage.',
      'Acid Splash':'Orb deals 1d3 acid damage.',
      'Aid':'+1 on attack rolls and saves against fear, 1d8 temporary hp +1/level (max +10).',
      'Air Walk':'Subject treads on air as if solid (climb or descend at 45-degree angle).',
      'Alarm':'Wards an area for 2 hours/level.',
      'Align Weapon':'Weapon becomes good, evil, lawful, or chaotic.',
      
      ...
      
      'Weaken Powder':'Targeted firearm's ammunition halves the firearm's range and imposes a –2 penalty on damage rolls.',
      'Wilderness Soldiers':'Nearby plants aid you in combat.',
      'Wreath of Blades':'Four mithral daggers speed around you, attacking nearby creatures and protecting your spellcasting from attacks of opportunity.',
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多