作为程序员,我们经常会被客户问的一个问题一定是不是说很容易么,为什么花了这么长时间。不得不说,程序员可能是最糟糕的计划者,按时按点按计划完成的软件项目永远是下一个项目。一个项目的延期,有很多这样那样的原因,其中不得不说的一个原因就是很多代码想起来很容易,但是真的写起来,细节里全是魔鬼。在这个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. MyBatis源码解析【5】工厂的构建

    前言 这个分类比较连续,如果这里看不懂,或者第一次看,请回顾之前的博客 http://www.cnblogs.com/linkstar/category/1027239.html 终于算是把装备弄齐全 ...

  2. Codeforces Round #418 (Div. 2).C two points

    C. An impassioned circulation of affection time limit per test 2 seconds memory limit per test 256 m ...

  3. java基础07 多线程

    在学习操作系统时,我们会学习进程和线程,那么进程和线程又是什么东西呢? 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程(thread) ...

  4. Ambari 2.4.2 汉化

    1.ambari-web (1)apache-ambari-2.4.2-src/ambari-web/app/messages.js 该文件是KeyValue文件,3000多行.将Value部分翻译成 ...

  5. MySQL数据库“十宗罪”(十大经典错误案例)

    Top  1: Too many connections(连接数过多,导致连接不上数据库,业务无法正常进行) 问题还原 1 2 3 4 5 6 mysql> show variables lik ...

  6. win10 设置默认输入法为英文,ctrl +shift切换中文

    控制面板-更改输入法,这个界面出现的是电脑现在安装的语言,每个语言中可能有多个输入法,比如我的有微软的和qq的,谁在上谁就是系统的默认语言(本人当然是中文在上),英文中有美式键盘. 如果想要电脑启动的 ...

  7. javascript数组(1) ——sort的工作原理及其他数组排序方法

    一说到数组排序,最直观的想法就是用sort啊! 请问不用使用sort方法还可以使用什么方法进行数组排序? 比如 :  快速排序法.合并排序法.冒泡排序法.选择排序法.插入排序法.布尔排序法.交互排序. ...

  8. Spring Ioc-依赖注入的几种方式

    一 setter方法注入 配置文件如下: <bean id="helloAction" class="org.yoo.action.SpringSetterHell ...

  9. Python:使用Kivy将python程序打包为apk文件

    1.概述 Kivy是一套Python下的跨平台开源应用开发框架,官网,我们可以用 它来将Python程序打包为安卓的apk安装文件.以下是在windows环境中使用. 安装和配置的过程中会下载很多东西 ...

  10. C#中的数据类型转换

    数据类型在一定的条件下是可以相互转换的,如将int型数据转换成double型数据.C#允许使用两种转换方式:隐式转换和显式转换. 1.隐式转换 隐式转换:从类型A到类型B的转换可以在所有情况下进行,执 ...