写入文本文件被切断

时间:2017-03-22 23:58:12

标签: python json python-2.7

我目前正在研究一些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个法术中应该存在的大约30个法术。基于一些反复试验,我发现了以下内容:

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

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

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

3 个答案:

答案 0 :(得分:1)

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

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

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。而你仍然想在最后关闭文件。

答案 1 :(得分:0)

您需要在文件末尾执行fWrite.close()或使用相同的&#34;使用&#34;上下文管理器与法术文件一样。

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

答案 2 :(得分:0)

您可以使用Python2尝试此示例,该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.', 的代码:

Traceback (most recent call last):


File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/arbiter.py", line 557, in spawn_worker
    worker.init_process()
  File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/workers/base.py", line 126, in init_process
    self.load_wsgi()
  File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/workers/base.py", line 136, in load_wsgi
    self.wsgi = self.app.wsgi()
  File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
    return self.load_wsgiapp()
  File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/root/merci_api/venv/lib/python3.5/site-packages/gunicorn/util.py", line 357, in import_app
    __import__(module)
  File "/root/merci_api/main.py", line 12, in <module>
    import transaction_commit
  File "/root/merci_api/transaction_commit.py", line 9, in <module>
    import cfdi
  File "/root/merci_api/cfdi.py", line 15, in <module>
    from M2Crypto import RSA
  File "/root/merci_api/venv/lib/python3.5/site-packages/M2Crypto-0.25.1-py3.5-linux-x86_64.egg/M2Crypto/__init__.py", line 26, in <module>
    from M2Crypto import (ASN1, AuthCookie, BIO, BN, DH, DSA, EVP, Engine, Err,
  File "/root/merci_api/venv/lib/python3.5/site-packages/M2Crypto-0.25.1-py3.5-linux-x86_64.egg/M2Crypto/SSL/__init__.py", line 24, in <module>
    from M2Crypto.SSL.SSLServer import (ForkingSSLServer, SSLServer,
  File "/root/merci_api/venv/lib/python3.5/site-packages/M2Crypto-0.25.1-py3.5-linux-x86_64.egg/M2Crypto/SSL/SSLServer.py", line 12, in <module>
    from SocketServer import BaseServer, ForkingMixIn, TCPServer, ThreadingMixIn
ImportError: No module named 'SocketServer'