作为程序员,我们经常会被客户问的一个问题一定是不是说很容易么,为什么花了这么长时间。不得不说,程序员可能是最糟糕的计划者,按时按点按计划完成的软件项目永远是下一个项目。一个项目的延期,有很多这样那样的原因,其中不得不说的一个原因就是很多代码想起来很容易,但是真的写起来,细节里全是魔鬼。在这个Epic Fail的系列中,我会记录一些在我平常写代码的过程中遇到的那些本来很简单却花了很长时间的有趣问题。这个系列会不定时更新,不断记录我写代码中的糗事,希望我永远不用更新:)。
 
作为开篇,记录一个花了我1个多小时的python脚本。故事的背景是这样的,我有个测试数据,分散在几个csv中,我想把它们合并到一个csv中。作为程序员,让我手动把每个csv文件打开,复制粘贴到另外一个文件里这种没技术含量的方法当然不会做。而且将来我要是有很多文件要合并呢?我还能真的一个一个拷啊。其实我只要合并4个文件,手动的方式可能是更快的方法,这当然是后话。
 
作为一个“精于”python又不会诸如sed一般的神奇unix命令的我,自然打开python写下了下面的代码:
import os

def merge_all(path, output_file):
output = open(os.path.join(path, output_file), 'w')
header_writen = False
for f in os.listdir(path):
full_name = os.path.join(path, f)
if os.path.isfile(full_name) and f.endswith('.csv'):
input = open(full_name)
header = input.readline()
if not header_writen:
output.write(header)
header_writen = True
input.readline()
input.readline()
line = input.readline()
while line:
output.write(line)
line = input.readline()
input.close()
output.close()
这段代码平淡无奇,我不到5分钟就一挥而就。整体的逻辑就是遍历文件夹,打开所有的csv文件,对header只输出一次,第二行和第三行跳过,因为这两行的数据我不需要,然后把下面的每行写入输出文件。
 
运行脚本,数据合并一切正常,但是数据的header,却没有。这种时候,作为程序猿第一反应就是再运行一遍,由于脚本偷懒,我把输出文件写在了输入文件夹中,我手动把生成的输出文件删了,重新运行了一次。还是一样的结果,数据都合并了,但是还是没有文件头。这个时候,作为程序猿的第二反应就是再运行一遍,无奈还是一样的结果。
 
这时,我不得不面对上面的代码有问题的结论。这也是程序员最郁闷的时候,因为我对问题一点头绪都没有。这时自己手动在生成的文件中加上头行应该是最好的选择,但是作为程序员是很难接受这种做法的。
 
开始排错,既然是header没写,那么一定是我的header_writen的逻辑有问题,可这个代码咋看也看不出有啥问题啊。经过多次纠结后,我加入了一行日志代码:
if os.path.isfile(full_name) and f.endswith('.csv'):
print 'Processing ' + full_name + '…'
这时问题的症结终于出现了,那就是第一个被遍历的csv文件是我生成的输出文件!
 
发现了问题解决起来就很容易了:
for f in os.listdir(path):
if f == output_file:
continue
在循环中加入这个简单的逻辑,问题就解决了。这个小小的细节,竟然花了我这么长时间。
 
反思这个问题,如果不是我的输出文件名在listdir中排在第一个我可能会遇到更大的问题,在生成的文件中出现重复数据。而这个问题很可能被我忽略。
 
这个问题又如何避免呢?我认为最好的方法就是我不应该图省事把数据输出文件写入读取文件夹。这个决定完全是为了省事,但是也就破坏了输入文件夹的状态,而这个状态是我完全没意识到的。 

程序员的Epic Fail [0]的更多相关文章

  1. 野生程序员对.NETFramework 4.0 ThreadPool的理解

    ThreadPool 类 提供一个线程池,该线程池可用于执行任务.发送工作项.处理异步 I/O.代表其他线程等待以及处理计时器. 命名空间:   System.Threading程序集:  mscor ...

  2. 35岁老半路程序员的Python从0开始之路

    9年的ERP程式开发与维护,继而转向一年的售前,再到三年半的跨行业务,近4的兜兜转转又转回来做程式了,不过与之前不同的,是这次是新的程序语言Python, 同时此次是为了教学生而学习! 从今天开始,正 ...

  3. 程序员的长安十二时辰:Java实现从Google oauth2.0认证调用谷歌内部api

    最近公司在做一个app购买的功能,主要思路就是客户在app上购买套餐以后,Google自动推送消息到Java后端,然后Java后端通过订单的token获取订单信息,保存到数据库. Java后端要获取订 ...

  4. Java 程序员技能导图 1.0

    做Java开发已经一年,并非科班出身,在毕业工作三年后毅然决然辞职,参加培训机构从零开始.在这期间迷茫.失望.绝望时常伴我左右,但是在不断自我提高与努力中渐渐看到一些小小的成果使我不断坚信自己的选择并 ...

  5. 0~5年一个Java程序员的晋升之路

    在程序界流行着一种默认的说法叫“黄金5年”,也就是一个程序员从入职的时候算起,前五年的选择直接影响着整个职业生涯中的职业发展方向和薪资走向,如何走好这5年,彻底从一个刚入行的菜鸟蜕变成可以以不变应万变 ...

  6. NEL程序员专用轻钱包 进入0.01状态了

    这个轻钱包能干什么,现在就能在测试网看个余额,转个帐,调用个合约. 而且功能非常程序员化 你会说是不是没啥用   但是他有非常有用,因为他可以很容易的拼出NEOGUI拼不出来的交易 比如参与ICO交易 ...

  7. 黑马程序员面试宝典(Java)Beta6.0免费下载

    场景 JavaSE基础 面向对象特征以及理解 访问权限修饰符区别 理解clone对象 JavaSE语法 java有没有goto语句 &和&&的区别 如何跳出当前的多重嵌套循环? ...

  8. 2020Java程序员架构师面试宝典,学习后面试必过,震惊,本人通过这篇教程,拿到了0个offer

    1. 引言 Java后端学习路线 <吐血整理>顶级程序员工具集 https://github.com/AobingJava/JavaFamily 跟上Java8 经历阿里.头条.腾讯等知名 ...

  9. gevent程序员指南

    gevent程序员指南 由Gevent社区编写 gevent是一个基于libev的并发库.它为各种并发和网络相关的任务提供了整洁的API.   介绍 本指南假定读者有中级Python水平,但不要求有其 ...

随机推荐

  1. 以芯片直读方式得到的全盘镜像解析及ext4日志区域解析

    之前在centos中分析了/dev/sda1下的结构,但当对象是一块以芯片直读方式作出来的全盘镜像呢? 这次以安卓手机的全盘镜像为对象,尝试按照ext4文件系统结构手动解析,加强对ext4文件系统.E ...

  2. 安装WIA组件

    下载地址: http://pan.baidu.com/s/1bnGU5Nx 安装方法: 将下载后的WIAAutSDK.zip解压,复制wiaaut.dll到C:\Windows\System32,注册 ...

  3. require.js(浅聊)

    一.require 了解requirejs之前首先明白什么是模块化: 1.什么是模块化? 模块化设计是指在对一定范围内的不同功能或相同功能不同性能.不同规格的产品进行功能分析的基础上,划分并设计出一系 ...

  4. Struts2框架05 result标签的类型

    1 result标签是干什么的 就是结果,服务器处理完返回给浏览器的结果:是一个输出结果数据的组件 2 什么时候需要指定result标签的类型 把要输出的结果数据按照我们指定的数据类型进行处理 3 常 ...

  5. Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配)

    Luogu 1559 运动员最佳匹配问题(带权二分图最大匹配) Description 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的 ...

  6. TCP简单通讯

    客户端代码: package com.kaige123.net01; import java.io.IOException; import java.io.InputStream; import ja ...

  7. 创建 Machine - 每天5分钟玩转 Docker 容器技术(46)

    对于 Docker Machine 来说,术语 Machine 就是运行 docker daemon 的主机.“创建 Machine” 指的就是在 host 上安装和部署 docker.先执行 doc ...

  8. 获取cpu真实型号

    感谢文洋兄的思路.亲测有效. [root@storage GetCpuType]# ./main.o Intel(R) Xeon(R) CPU C5528 @ 2.13GHz #include < ...

  9. Epii.js 一个极其简单的Js模板引擎

    Epii.js 简约而不简单的Js模板引擎 Epii.js 简约而不简单的JavaScript模板引擎 # 特性 一个轻量级模板引擎,可快速实现数据与ui绑定(数据变动,UI自动变动),快速实现事件绑 ...

  10. Mysql的JDBC

    Java程序可以通过JDBC链接数据库,通过JDBC可以方便的访问数据库,不必为特定的数据库编写专门的程序. 需要先配置mysql-connector-java-5.0.8-bin.jar 使用JDB ...