python数据处理,字典生成的一个问题
高洛峰
高洛峰 2017-04-18 09:25:14
[Python讨论组]
高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全部回复(5)
大家讲道理

這裡是不求切割文件的作法, itertools.product 可以幫你完成地更簡潔:

import itertools

with open('zidian.txt', 'w') as z:
    with open('file1.txt') as f1, open('file2.txt') as f2:
        for a, b in itertools.product(f1, f2):
            a, b = a.strip(), b.strip()
            print(a+b, file=z)

切割輸出的做法:

import itertools

with open('file2.txt') as f2:
    for key, group in itertools.groupby(enumerate(f2), lambda t: t[0]//5):
        with open('file1.txt') as f1, open('zidian-{}.txt'.format(key), 'w') as z:
            for a, (_, b) in itertools.product(f1, group):
                a, b = a.strip(), b.strip()
                print(a+b, file=z)

稍微說一下你原本代碼的一些問題:

  • f = open('zidian.txt','w') 你在這裡 open 了文件可是卻忘記關閉了, 讀寫文件還是使用 with 的作法會比較好

  • dict.readlines(), 若非萬不得已, 不要使用 readlines, 千萬記得!! 請參考這篇文章 文本格式轉換代碼優化

  • 另外, dicdict 這個字, 在 python 中有著獨特的意義, 稍微有點經驗的 python programmer 都會認為他們是 python dictionary, 這容易造成誤會


我回答過的問題: Python-QA

阿神

呃, 理解错题主的意思, 重新写下代码, 我承认用filehandler.readlines()是自己打脸了~
其实如果只是觉得生成的文件有些大的话, *nix有一款自带的小工具split非常适合, 可以随意把大文件拆分成若干小的
下面的代码如果不考虑结果分割可以简单修改write2file函数, 然后id_generator函数及相关模块(random, string)可以删掉

def write2file(item):
    with open("dict.txt", "a") as fh, open("file1.txt", "r") as f1:
        for i in f1.readlines():
            for j in item:
                fh.write("{}{}\n".format(i.strip(), j))
       
import random
import string
from multiprocessing.dummy import Pool


def id_generator(size=8, chars=string.ascii_letters + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))


def generate_index(n, step=5):
    for i in range(0, n, step):
        if i + step < n:
            yield i, i+step
        else:
            yield i, None


def write2file(item):
    ext_id = id_generator()
    with open("dict_{}.txt".format(ext_id), "w") as fh, open("file1.txt", "r") as f1:
        for i in f1.readlines():
            for j in item:
                fh.write("{}{}\n".format(i.strip(), j))


def multi_process(lst):
    pool = Pool()
    pool.map(write2file, b_lst)
    pool.close()
    pool.join()


if __name__ == "__main__":
    with open("file2.txt") as f2:
        _b_lst = [_.strip() for _ in f2.readlines()]
        b_lst = (_b_lst[i: j] for i, j in generate_index(len(_b_lst), 5))
    multi_process(b_lst)

结果如图, 会生成若干dict_8位随机字符串的文本文档

其中一个内容dict_3txVnToL.txt

zhangwei123
zhangwei123456
zhangwei@123
zhangwei888
zhangwei999
wangwei123
wangwei123456
wangwei@123
wangwei888
wangwei999
...

以下是旧内容

满足你的渴望,放码:

with open("file1") as f1, open("file2") as f2, open("new", "w") as new:
    b = f2.readline().strip()
    while b:
        a = f1.readline().strip()
        for i in range(5):
            if b:
                new.write("{}{}\n".format(a, b))
            else: break
            b = f2.readline().strip()

每次只按行读取,无论多大的文件都能hold住,节能环保,结果示意:

$ head new
zhangwei123
zhangwei123456
zhangwei@123
zhangwei888
zhangwei999
wangwei666
wangwei2015
wangwei2016
wangwei521
wangwei123

PS:如楼上所说,尽量避免使用readlines方法,内存有限的情况下,如果碰到超大文件会是个灾难

阿神

把file2每行存到一个list里面,然后每次从list里面拿五个就行了啊

手头没有python,代码纯手写估计有错误。理解思想即可

names = []
with open('file1.txt','r') as username:
    for line in username.readlines():
        names.append(line)
    
list = []
with open('file2.txt','r') as dict:
    for line in dict.readlines():
       list.append(line)
for i in range(len(line) / 5):
    f = open('zidian' + str(i + 1) + '.txt', 'w')
    for j in range(5):
        for name in names:
            f.write(user.strip() + line[i * 5 + j] + '\n')
    f.close()
# 把除5的余数,即剩下的最后几行再写一个文件,代码不写了
PHP中文网

@dokelung 的itertools.cycle是个妙用,我还有更好的方法:

with open('file2') as file2_handle:
    passwords = file2_handle.readlines()
    # 当然了,就如楼上所说,用readlines不好,但是这不是绝对的,在你的文件没有大到内存吃不消的情况下,readlines会显著提高程序的性能(这句话是有问题的,前提是你没拿读文件的IO时间做其他的事)
    # 在我看来,几百万行的文件,那都不是事,我用python读取10G以上的文件都是常有的事
    # 当然了,尽量不要用readlines,这里只是为了我实现下面的算法方便
  
with open('file1') as file1_handle:
    name_password_dict = ['%s%s' % (line.rstrip(), passwords[i%len(passwords)]) for i, line in enumerate(file1_handle)]

# 有了name_password_dict还不是想干嘛干嘛,不管是分文件其他是什么的
高洛峰

简单来说增加一个计数器line,每匹配一组值line += 1,line为5的时候关闭文件,打开新的文件并置line为0.

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号