Writing to text file while reading one. (ValueError: I/O operation on closed file.)

Writing to text file while reading one. (ValueError: I/O operation on closed file.)

我目前正在编写一个脚本,该脚本以更基本的方式重新排列 JSON 数据,因此我可以 运行 通过另一个 YOLO 箱线图脚本来重新排列数据。到目前为止,我已经设法让脚本以我希望的格式打印数据。但是,我想将它保存在一个文本文件中,这样我就不必每次都 copy/paste 了。做起来似乎比最初预想的要难。

所以这是当前“有效”的代码:

import sys

data    = open(sys.argv[1], 'r')

with data as file:
    for line in file:
        split = line.split()
        if split[0] == '"x":':
            print("0", split[1][0:8], end = ' ')
        if split[0] == '"y":':
            print(split[1][0:8], end = ' ')
        if split[0] == '"w":':
            print(split[1][0:8], end = ' ')
        if split[0] == '"h":':
            print(split[1][0:8]) 

下面是将通过此脚本 运行 的数据集示例:

{
    "car": {
        "count": 7,
        "instances": [
            {
                "bbox": {
                    "x": 0.03839285671710968,
                    "y": 0.8041666746139526,
                    "w": 0.07678571343421936,
                    "h": 0.16388888657093048
                },
                "confidence": 0.41205787658691406
            },
            {
                "bbox": {
                    "x": 0.9330357313156128,
                    "y": 0.8805555701255798,
                    "w": 0.1339285671710968,
                    "h": 0.2222222238779068
                },
                "confidence": 0.8200334906578064
            },
            {
                "bbox": {
                    "x": 0.15803571045398712,
                    "y": 0.8111110925674438,
                    "w": 0.22678571939468384,
                    "h": 0.21111111342906952
                },
                "confidence": 0.8632314801216125
            },
            {
                "bbox": {
                    "x": 0.762499988079071,
                    "y": 0.8916666507720947,
                    "w": 0.1428571492433548,
                    "h": 0.20555555820465088
                },
                "confidence": 0.8819259405136108
            },
            {
                "bbox": {
                    "x": 0.4178571403026581,
                    "y": 0.8902778029441833,
                    "w": 0.17499999701976776,
                    "h": 0.17499999701976776
                },
                "confidence": 0.8824222087860107
            },
            {
                "bbox": {
                    "x": 0.5919643044471741,
                    "y": 0.8722222447395325,
                    "w": 0.16607142984867096,
                    "h": 0.25
                },
                "confidence": 0.8865317106246948
            },
            {
                "bbox": {
                    "x": 0.27767857909202576,
                    "y": 0.8541666865348816,
                    "w": 0.2053571492433548,
                    "h": 0.1805555522441864
                },
                "confidence": 0.8922017216682434
            }
        ]
    }
}

结果将如下所示:

0 0.038392 0.804166 0.076785 0.163888
0 0.933035 0.880555 0.133928 0.222222
0 0.158035 0.811111 0.226785 0.211111
0 0.762499 0.891666 0.142857 0.205555
0 0.417857 0.890277 0.174999 0.174999
0 0.591964 0.872222 0.166071 0.25
0 0.277678 0.854166 0.205357 0.180555

我没有打印这些行,而是尝试将它们写入一个新的文本文件,但是,我不断收到“ValueError: I/O operation on closed file.“ 错误。我猜这是因为我已经打开了一个,打开一个新的会关闭第一个?有没有一种简单的方法可以解决这个问题?还是太麻烦了,copy/pasting 打印结果是“最简单”的方式?

为什么不使用 jsoncsv 软件包??

import csv
import json

# import sys
# file = sys.argv[1]

file = "input.json"
output_file = "output.csv"

with open(file, "r") as data_file:

    data = json.load(data_file)

    with open(output_file, "w") as csv_file:
        
        writer = csv.writer(csv_file, delimiter=' ')

        for value in data.values():

            instances = value.get("instances")
            bboxes = [instance.get("bbox") for instance in instances]

            for bbox in bboxes:
                
                writer.writerow([
                    0, 
                    f"{bbox['x']:.6f}",
                    f"{bbox['y']:.6f}",
                    f"{bbox['w']:.6f}",
                    f"{bbox['h']:.6f}",
                ])

输出:

0 0.038393 0.804167 0.076786 0.163889
0 0.933036 0.880556 0.133929 0.222222
0 0.158036 0.811111 0.226786 0.211111
0 0.762500 0.891667 0.142857 0.205556
0 0.417857 0.890278 0.175000 0.175000
0 0.591964 0.872222 0.166071 0.250000
0 0.277679 0.854167 0.205357 0.180556

备注:

  • 了解您正在使用的输入文件格式很重要。了解 JSON here.
  • 我在这两个示例中将值四舍五入为 6 位数字(不确定要求是什么,但只需修改 f"{bbox['x']:.6f}" 以及该行之后的 3 行以适应您的用例)

,如果您想将jmespathcsvjson一起使用:

import csv
import json
import jmespath  # pip install jmespath

# import sys
# file = sys.argv[1]

file = "input.json"
output_file = "output.csv"

with open(file, "r") as data_file:

    data = json.load(data_file)
    
    bboxes = jmespath.search("*.instances[*].bbox", data)

    with open(output_file, "w") as csv_file:

        writer = csv.writer(csv_file, delimiter=' ')

        for bbox in bboxes[0]:
            
            writer.writerow([
                0, 
                f"{bbox['x']:.6f}",
                f"{bbox['y']:.6f}",
                f"{bbox['w']:.6f}",
                f"{bbox['h']:.6f}",
            ])

我建议将文件解析为 JSON 而不是原始文本。如果文件是 JSON,则将其视为 JSON 以避免不幸的情况,其中有效、缩小 JSON 并且缺少换行符使得将其视为字符串 a可能脆弱的正则表达式的噩梦。或者更糟的是,文件无效 JSON.

import json
import sys
with open(sys.argv[1], 'r') as f:
    raw = f.read()
obj = json.loads(raw)
print("\n".join(
    f"0 {i['bbox']['x']:.6f} {i['bbox']['y']:.6f} {i['bbox']['w']:.6f} {i['bbox']['h']:.6f}"
         for i in obj["car"]["instances"])
)