V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
zxCoder
V2EX  ›  问与答

Python 读取文件请教

  •  
  •   zxCoder · 2022-05-06 21:43:49 +08:00 · 1522 次点击
    这是一个创建于 937 天前的主题,其中的信息可能已经有所发展或是发生改变。

    读取一种类型的文本文件,里面内容是这样的:

    00401000 56 8D 44 24 08 50 8B F1 E8 94 B7 01 00 C7 06 74
    00401010 BE 54 00 8B C6 5E C2 04 00 CC CC CC CC CC CC CC
    00401020 C7 01 74 BE 54 00 E9 9E B8 01 00 CC CC CC CC CC
    00401030 56 8B F1 C7 06 74 BE 54 00 E8 8B B8 01 00 F6 44
    00401040 24 08 01 74 09 56 E8 E4 BA 01 00 83 C4 04 8B C6
    00401050 5E C2 04 00 CC CC CC CC CC CC CC CC CC CC CC CC
    00401060 8B 44 24 08 C3 CC CC CC CC CC CC CC CC CC CC CC
    00401070 C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
    00401080 8B 44 24 08 66 8B 08 8B 54 24 04 66 89 0A C3 CC
    00401090 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
    .....
    

    有好几十万行。

    我想把后面那些 16 进制的数字依次转换成 10 进制,存到一个 list 里。

    我现在代码读取很慢,读一个文件要几十分钟

    with open(f"{file_name}", "r") as rd:
        arr = []
        for line in tqdm(rd.readlines()):
            arr.extend([int(f"0x{a}", 16) for a in line.strip().split(" ")[1:]])
        return np.array(arr, dtype=np.ubyte)
    

    有没有更快的方法,求大佬解答

    16 条回复    2022-05-07 09:41:58 +08:00
    ysc3839
        1
    ysc3839  
       2022-05-06 21:52:29 +08:00 via Android
    没太看懂你的需求和代码,你是要转成十进制整数字符串吗?代码中好像没有相关操作
    至于解决的话,试试改成流式处理,即不要预先读取过多数据
    zxCoder
        2
    zxCoder  
    OP
       2022-05-06 22:05:50 +08:00
    @ysc3839 [int(f"0x{a}", 16) for a in line.strip().split(" ")[1:]] 我这里是把一行的十六进制转成十进制的。太多行了,跑半天
    ynyounuo
        3
    ynyounuo  
       2022-05-06 22:15:02 +08:00
    你这个需求似乎没有必要 serial
    zxCoder
        4
    zxCoder  
    OP
       2022-05-06 22:18:19 +08:00
    @ynyounuo 啥意思老哥
    imn1
        5
    imn1  
       2022-05-06 22:31:22 +08:00
    @zxCoder #3 的意思是让你整个文件读入 numpy 或者 pandas ,然后用一个函数 apply 到每个单元格

    内存足够的话整体读入,不够才需要逐行读入
    ysc3839
        6
    ysc3839  
       2022-05-06 22:38:11 +08:00 via Android
    @zxCoder 你这是转成整数,整数在计算机里是二进制的,并不是十进制。一般提到十进制、十六进制等指的都是相应进制的数字文本。
    zxCoder
        7
    zxCoder  
    OP
       2022-05-06 22:40:39 +08:00
    @imn1 懂了懂了 多谢
    dcsuibian
        8
    dcsuibian  
       2022-05-06 22:44:19 +08:00
    很久没接触 Python 了,看不太懂 arr.extend
    你这一行是 56 个字符,加一个回车一行 57 个。都是 ascii 算一个字节。一行就 57 个字节。算一百万行,就是 57x100x10000/1024/1024=54.3MB ,这么小的量。
    直接读进来放内存里,一秒都不到,明显是你这处理方式有问题。
    dcsuibian
        9
    dcsuibian  
       2022-05-06 22:47:19 +08:00
    而且仔细看才发现,你这 rd.readlines()函数调用的时候就已经全部读到内存了。
    clino
        10
    clino  
       2022-05-06 22:50:19 +08:00
    读取应该花不了太多时间,但是处理数据花的时间会比较多,你可以把处理数据的代码去掉测试一下看看。
    chi1st
        11
    chi1st  
       2022-05-06 22:57:33 +08:00
    用 pandas
    misaka19000
        12
    misaka19000  
       2022-05-06 23:19:34 +08:00
    先看一下瓶颈在哪啊,是 CPU 满了还是内存满了
    wangyongbo
        13
    wangyongbo  
       2022-05-06 23:56:19 +08:00
    你可以把你的文件发出来,让大家测试一下吗?
    ysc3839
        14
    ysc3839  
       2022-05-07 04:09:07 +08:00   ❤️ 1
    用你给的数据重复了 500000 次(你给的数据有十行,总共有五百万行了)输出到文件,然后用你的代码去掉 tqdm 后在本地跑了下,也就耗时 23 秒,哪要几十分钟?

    自己写的代码耗时 5 秒
    ```
    with open('test.txt', 'r') as f:
    arr = bytearray()
    for line in f:
    i = line.find(' ')
    if i == -1:
    print('!')
    break
    arr.extend(bytes.fromhex(line[i + 1:]))
    print(len(arr))
    ```
    空格请自行补全
    yzwduck
        15
    yzwduck  
       2022-05-07 07:40:59 +08:00
    @ysc3839 如果不介意多耗一点内存的话,这样写的代码会跑得更快。

    ```
    with open('test.txt', 'r') as fi:
    data.fi.read()

    arr = bytes.fromhex(re.sub(r'^[0-9A-Fa-f]+ ', '', data, flags=re.MULTILINE))
    ```
    BingoXuan
        16
    BingoXuan  
       2022-05-07 09:41:58 +08:00
    想起客户提供的同行的烂代码,处理 30 秒 wave 文件要 35 秒

    pattern = re.compile('[0-9A-F]{2}')
    def read_file(name):
    ----with open(name,'r') as f:
    --------while True:
    ------------l = f.readline()
    ------------if not l:
    ----------------break
    ------------for x in pattern.findall(l):
    ----------------yield int(x,16)
    result = [y for y in read_file('some file')]
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5174 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 03:47 · PVG 11:47 · LAX 19:47 · JFK 22:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.