写一本技术书籍

2023-11-13

作者:董伟明
链接:https://zhuanlan.zhihu.com/p/22207407
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在过去的8个多月的时间里面,我完成了一本504页的《Python Web开发实战》。本文就是写这本书的一些感悟和心得,如果你准备写一本书(无论是出版社约稿还是想放在Github开源),希望本文对你能有一些帮助。如果你准备购买本书,也希望你能看到成书背后的一些故事。

--- 2016.11.10 插播 ---

这本书已经确定将输入到台湾

--- end ---

写博客 vs 写书

我从2010年开始写「技术博客」,到现在已经6年了。博客记录了我技术成长中的一些值得分享的经验,一方面希望惠及其他人,一方面作为一个连Evernote都不用的人,得有个平台记录这些技术笔记方便日后查看。首先我先承认博客写的并不好,主要原因是我的博客写的不够通熟易懂、深入浅出,我个人也不太愿意掰开了、揉碎了地讲的非常细致,在很多细节上是故意留给读者思考的空间。为什么这么做呢?因为我之前也喜欢「拿来主义」,看完之后觉得写的非常好,懂了,可是一段时间后就忘记了,我想这是因为这不是自己思考的结果,所以印象不会太深。我不太愿意帮这种倒忙。

我不做知识管理,脑袋里放了好多理解、经验,可是并没有系统的梳理过,写博客时候没关系,反正选题的内容窄,主题明确,写起来也会比较随意,理解不深或者理解错误也不会造成多大的损失,最多把博客改一改嘛。

写书完全不一样。

写书则得把握全书的基调,清楚书的结构,还得完全想好要表达给读者什么。我希望尽可能的深入细节,让读者看完就懂,原来那些比较模糊的细节要尽力的去搞懂,否则书出版了可就后悔不得了。这对我是极大的挑战,因为写博客的习惯改起来非常不容易,还得花费大量的时间去验证之前不确定的那些技术点,有些已经觉得理解了的技术点也得反复验证。

如何确定章节

在一开始,我花了一周多的时间在思考在书中要放什么内容,后来基本上自己已经清楚章节的安排,以及我希望传达给读者的方式。但是,这只是我所想的。

看过一本叫做《你以为你以为的就是你以为的吗》的书,它教会了我反思自己,对自己产生更多疑问。我当然希望覆盖更多的读者,但是我并不知道读者们的痛点有哪些,他们更想获得那些我熟悉的内容。我先发了篇博客,有同学留言或者同其他渠道告诉我一些诉求,感谢。我有一个人数5百多的QQ群,一个两百多的微信交流群,还有一些圈内好友的小组织,所以有段时间我经常在里面骚扰大家。问题无外乎2种:「你希望在书中看到哪方面的内容?」和「以你的经验,那些内容是必要的、有意义的?」。通过反馈,整书的轮廓就是这样慢慢显现出来了。和我之前想的还是有很多不一样的地方,举几个调查的结果:

1. 大家对爬虫、并发编程的热情最大。所以一本Web开发方面的书里面,竟然包含了一章「Python并发编程」。当然,Web开发者也是需要并发编程能力的。

2. 大家对产品运维的过程都希望有一些了解,所以书中对Fabric、SaltStack和Ansible都进行了较深入的介绍。

3. 我之前对「测试和持续集成」和「网站架构」等章节安排了比现在多很多的内容,但是大家的反馈看来并没有多少热情。

4. 大家对Python语法,编程技巧等方面热情也很大,但是受限于本书的选题和篇幅,只放了一章「Python进阶」。

我是这本书的舵手,我会听取反馈意见,但是无法满足所有的人的需要。如果书中的内容都面面俱到,由浅入深,我想三千页也讲不完,就像一位作序的老师说的,其实书中每章都能单独成书。

写这本书对我而言,最大的遗憾就是无法满足所有人的口味。就像编辑说的:「如果一本书可以解决所有问题,我们还怎么吃饭?」我把这本书的受众定位给有一定Python经验的开发者,其实本书不算难,讲的内容也算是互联网环境中的标准解决方案,太偏的,大家用到的机会少就不放进书中了。

控制篇幅

我曾经调查过页数和购买欲望的关系。有一小部分人觉得书太厚了就有畏惧情绪。大部分人觉得无所谓,只要内容认可就好。对我个人而言,我买书基本上是因为看目录中有我一直想了解的或者之前了解的不深刻的内容,积累到我认为性价比合适了就买,通常这本书的其他章节只是简单的翻翻甚至不看。我和编辑的共识是不要超过500页。一则这个选题以我之前看其他书籍的经验,基本就是这么个页数了;再则书厚了价格也要上去,对读者是一种负担;我和编辑都不喜欢拖拖拉拉,我也不靠写书挣钱,所以一开始的页数就是这么权衡出来的。

一开始列了一个大纲,列出了每个章节名字,以及预期这章节要写多少页。这里有个坑儿,Mou编辑器是左边编辑源文件,右边显示渲染后的效果,这个页数不是实际出版的页数,而是转化后的页数。写完一节就把真实的页数记录到大纲中,心里有个数。但是写完第七章之后,我就意识到按这个速度,肯定最后要超500页。所以从第八章开始,对页数控制的更严格,也做好了最后排版删除内容的准备。等写完之后,不出所料,第一次把书稿按照某本已出版的书的格式转化成pdf,页数为640页。

也就是说,为了控制篇幅,我要开始删除一些章节了。删除怎么安排的呢?

1. 首先去掉那些个人理解比重大的,没有把握的内容。

2. 接着去掉一些没有在实际生产环境中被验证的内容。

3. 精简一些不太重点的,普及率相对低的内容。比如之前「模板」中对Jinja2、Mako的篇幅要多一倍,还讲到了Plim。顺便提一下,Plim在豆瓣一些应用中有使用,但是外界还没听到过用它的,本来写书也是为了推广它,受限于篇幅去掉了。

写作方式

我的写作方式是先列出大的章节,然后逐步细化,虽然我基本是从第一章到最后一章这样写下来的,但是未必是按照顺序来写,可以先编写自己最熟悉的部分,然后逐步完善。有些时候我确实是跳着写或者同时写2-3节的时候,一般是因为在在前一节卡住了,比如我在写DPark的时候,由于本地环境运行不起来而无法继续,先写其他章节;还有就是一节的内容写的太久太枯燥了,换个自己擅长的、新鲜的章节。

我使用Mou写Markdown的书稿,但是由于Mou在一些细节上做的并不好,完成一节还是会本地跑gitbook看看效果的。

和编辑做书稿review主要靠Google Drive,后来在大妈的提醒下,使用了Gitbook和Disqus插件,我和作序老师们的review基本都是在http://gitbook.io上的私有项目里完成的。

规划内容

我选择把某个软件放到书里面肯定是有原因的,比如它是业界解决对应问题的主流方案,比如它对Web开发是有意义的。首先铺垫这些原因,以及它如何解决这些痛点。接着是它的安装、配置,保证读者可以运行起来。然后通过一些实际的案例让读者知道怎么用。除此之外,还得尽量丰富内容,如和其他未在本书出现的竞品的对比分析,工作中实际经验、高级定制玩法等。我比较喜欢列表式的表达,这可能和提PR的习惯有关。大体是这样的格式:

使用XX的常见场景如下:

1. AAA。
2. BBB。
3. CCC。

或者:

这种方式有如下优点:

1. AAA。
2. BBB。
3. CCC。
4. DDD。

写作的时候,我尽力把自己换位到初学者的角度。我确实这样走过来的,只是把我学习的过程遇到的痛点,作为写作的重点。书中很偶然也会出现了在官方文档等地方能看到的内容,原因是我觉得它真的很重要,一定要着重的写出来。

有了风格,还得有一个验收的指标。我和编辑的约定是,让编辑以一个非技术从业者的角度阅读,看看读完之后,有没有了解到「它是啥」、「它能做啥」、「什么时候该用」、「它怎么玩」,「它有什么坑」等,如果编辑没有看懂,那么这节就是不合格的,再改进。

邀请作序和推荐语

首先声明,这不是编辑强制的。这是在成书后期,一个圈内好友建议的,我才意识到。问了下编辑,说人数不限。对我来说,这也是一个挑战,因为之前反正编辑又不懂技术,写出来什么就是什么。但是这些东西有没有理解正确,有没有偏离主流我也不能完全肯定。邀请别人作序和写推荐语,其实相当于项目中找人来review你的代码,我反而觉得被业界专家和其他公司的人来吐槽下更能让本书变好。

这个过程还是对我有比较深的感触的。因为大家说话有些时候不会像同事一样客气,嗯,我的心理素质还不错^.^。其次是确实学到了很多东西,而且让我对第4-5章进行的大量的重构和整理。所以我建议如果你写书,一开始就可以想好要不要邀请别人,还可以考虑让老师们分段的介入,甚至在列出大纲的时候就能给意见,这样在后期还是能省不少力的。

BTW,本书作序和推荐阵容非常强大。

写书的收益

这本书都是利用各种晚上、周末等时间完成的。我们先来计算一下写书花的时间吧。

这本书从2015年圣诞节左右开始,姑且按照2015年12月20日开始。写作完成时间为2016年5月24日。在接下来的2个多月的时间里面就是和编辑、评审老师们进行讨论和修改,其中也包含了了我对一些细节内容的调节,主要原因是事后想起来更好的表达方式,以及添加遗漏部分。8月15日基本结束写书工作。

我的日常比较规律:

1. 晚上8点半左右到家,接着陪女儿,一直到10点左右女儿入睡,如果没有其他的事情, 10点半到深夜1点半(早期是1点,后来发现进度不足以满意预期,开始晚睡)就是写书的时间。

2. 周末还是尽量找时间陪女儿,每周一般都会有一天要出去玩,除此之外要帮助老婆分担些日常事务。其实很少有机会能坐下来好好写一个小时的书,总是被各种事情打断,效率不高。周末总体上有多半天的时间能写书,大概10个小时。

好! 我们计算下整体写书的耗时。从2015年12月20日到2016年8月15日一共240天,也就是34周多2天,每周一到周五,每天3小时,周末十个小时。其中有3个礼拜老婆带着女儿避暑去了,这也是给我放假,那段时间我的写作时间能到2倍左右。还得去掉有2周我去度假了。粗糙一点总计875小时:

In : (3 * 5 + 10) * (34 + 3 - 2)Out: 875

稿酬我选用「版税制」,书的定价是105,而我每本书可获得其中的8%,首印3000册,需要缴纳20%的税。我的收入是:

In : 105 * 3000 * 0.08 * (1 - 0.2)Out: 20160.0

最后算一下我的时薪:

In : '{0:0.2f}'.format(20160.0 / 875)Out: 23.04

如果按每月工作22天,每天8小时的标准。 额,我的月薪如下:

In : 20160.0 / 875 * 8 * 22Out: 4055.04

没有写书之前,尤其是刚工作时候,虽然没有吝啬过,但还是觉得买技术书比较奢侈。等我真的写了,才知道做知识的分享有多难,写出来说不定被喷的得多惨呢。

我还了解了一下,翻译书的译者更辛苦,因为他们得斟酌原作者每一句话,试着从原作者的角度理解,甚至于在其中发现错误并标注出来。对我来说,这显然不如自己写作那样畅快。所以大家对译者更宽容一些吧。

--- UPDATE ---

看评论画风不咋对。买书得是因为它有用啊!说出来只是让大家了解写书的收益,看评论区:

12d60f1b4eb27b83fb2eb111e5200589_b.png我得承认这是对的。但是在国内Python相对小众,如果确实大家觉得好,书能重印的话我的稿费确实也能挣400w... 哈哈。但目前就挣了这2W多,如果之后重印了我会来专栏更新状态的。

--- update 2016.09.16 ---

在预售时书全部发完了,连京东自营都没有抢上,所以又重印了。那么上面说的我能获得收益就要翻个倍了。感谢大家支持。

--- update 2016.10.20 ---

第三次重印,这次重印修正了这一个月收集到的本书的反馈和勘误,虽然只有2k册。

PS: 之后将不再update

--- end ---

不要纠结 Python 2 or Python 3

正文完

知乎Live入口: 点击报名《董伟明 的 Live -- Python 工程师的入门和进阶》

欢迎关注本人的微信公众号获取更多Python相关的内容(也可以直接搜索「Python之美」):

本文转自ljianbing51CTO博客,原文链接: http://blog.51cto.com/ljianbing/1895166,如需转载请自行联系原作者
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

写一本技术书籍 的相关文章

  • 如何使用python从文件夹中的pdf中提取文本并将其保存在数据框中?

    我有很多文件夹 每个文件夹都有几个 pdf 文件 也有其他文件类型 如 xlsx 或 doc 我的目标是提取每个文件夹的pdf文本并创建一个数据框 其中每条记录都是 文件夹名称 每列以字符串形式表示该文件夹中每个pdf文件的文本内容 我设法
  • 如果值已经是字符串,我是否应该避免转换为字符串?

    有时您必须使用列表理解将所有内容转换为字符串 包括字符串本身 b str a for a in l 但我必须这样做 b a if type a str else str a for a in l 我想知道是否str在字符串上已经足够优化no
  • 使用 matplotlib 在图像数据之上对线网格进行像素精确定位

    我试图在 python 库 matplotlib 显示的图像网格顶部精确地覆盖 1 像素宽线的网格 不幸的是 我似乎无法对结果进行足够精细的控制 以实现线网格与数据网格的正确对齐 如下面的代码所示 结果似乎总是很接近 但并不完全正确 我尝试
  • 在Python中用空格分割字符串——保留带引号的子字符串

    我有一个像这样的字符串 this is a test 我正在尝试用 Python 编写一些内容 以将其按空格分开 同时忽略引号内的空格 我正在寻找的结果是 this is a test 附言 我知道您会问 如果引号内有引号会发生什么 嗯 在
  • BeautifulSoup 不适用于某些网站

    我有这个脚本 import urrlib2 from bs4 import BeautifulSoup url http www shoptop ru page urllib2 urlopen url read soup Beautiful
  • pandas:使用运算符链接过滤 DataFrame 的行

    大多数业务在pandas可以通过操作符链接来完成 groupby aggregate apply等 但我发现过滤行的唯一方法是通过普通的括号索引 df filtered df df column value 这没有吸引力 因为它需要我分配d
  • 在Python中将距离矩阵转换为成对距离列表[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 假设Python中有以下距离矩阵 0 1 2 3 0 0 1 4 8 1 1 0 3 7 2 4 3 0 3 3 8 7 3 0 我想
  • django/whitenoise 存储后端导致错误

    我在调试关闭时在 heroku 上运行 django 应用程序时遇到了 500 错误 使用 rollbar 了解发生错误的原因后 它报告了以下内容 ValueError The file media img 1 jpg could not
  • PySerial 和多个 Python 安装出现问题

    我的 Windows 7 计算机上有 Python 2 4 4 和 3 1 3 我想使用 PySerial 听说是内置的 所以我尝试了一下import serial在两个版本中 两者都造成了Import Error 然后我从以下位置下载了w
  • 使用 selenium 在 python 中切换到弹出窗口

    如何在下面的 selenium 程序中切换到弹出窗口 我已经查找了所有可能的解决方案 但无法解决它们 请帮忙 from selenium import webdriver from splinter import Browser from
  • Pandas Dataframe.to_csv 小数=',' 不起作用

    在 Python 中 我正在将 Pandas Dataframe 写入 csv 文件 并希望将小数分隔符更改为逗号 像这样 results to csv D Data Kaeashi BigData ProcessMining Voorbe
  • 如何计算具有较大中间值的总和

    我想计算 for n m两个值都是 1000 以内的整数 最终结果是一个不大于 1000 的数字n但中间值对于 python 来说太大了 无法处理 你怎么解决这个问题 我将函数定义如下 from scipy misc import comb
  • ctypes.ArgumentError:不知道如何转换参数

    我在C库中定义了一个函数 如下所示 int Test char str1 int id1 char str2 float val float ls 我想在Python中使用它 所以我编写了以下Python代码 str1 a str2 b i
  • Django外键:获取相关模型?

    是否可以通过外键字段本身获取外键的相关模型 例如 如果我有 3 个模型 class ModelA models Model field1 models CharField max length 10 class ModelB models
  • 带参数的 Python 列表过滤

    python中有没有一种方法可以在列表上调用过滤器 其中过滤函数在调用期间绑定了许多参数 例如有没有办法做这样的事情 gt gt def foo a b c return a lt b and b lt c gt gt myList 1 2
  • Django 1.6:如何在视图中访问静态文件

    我已经尝试过解决方案here https stackoverflow com questions 11721818 django get the static files url in view这对我不起作用 我正在为 Python 创建一
  • 如何下载和使用对象检测数据集(例如 coco 或 pascal)

    我对物体检测领域非常陌生 我想知道是否有人可以帮助我下载和使用对象检测数据集 例如 coco 或 pascal 当我下载数据集后访问他们的网站时 我觉得我不知道应该如何处理它们 我知道这个问题很愚蠢 但是开始的提示可能非常有用 谢谢 我正在
  • 如何使用 Python 3 在 OpenCV 3 上正确加载 cv2.KeyPoint 和描述符?

    有一天 我不得不恢复一个使用 OpenCV 3 和 Python 2 7 的旧项目 在此代码中 要加载 cv2 KeyPoint 我执行以下操作 import numpy as np import cPickle import cv2 ke
  • 使用 PyCharm 分析 Django

    即使在开发环境中 我的应用程序也相当慢 所以我想找出是什么导致它变慢 以便我可以尝试修复它 我了解调试工具栏 根据它的报告 数据库查询和下载的源都不是问题 所以它一定是业务逻辑 但是 我无法使用 Django 服务器运行 PyCharm 分
  • Mac 上的 PythonXY?

    如何在 Mac OS X Lion 上安装 Python 我开始了 它应该能够通过 macports 但无论如何我找不到 mac ports 网站上所述的端口 pythonXY 我对 MAC 和 pythonXY 都不太了解 但在 pyth

随机推荐

  • docker安装gitlab(离线)

    总体思路 找一台可以联网的linux 下载docker的RPM依赖包而不进行安装 yum localinstall 将所有依赖的rpm环境打包好 再在无网环境中解压逐一安装 rpm force nodeps 同理 docker镜像也通过联网
  • 10 个顶尖的 Linux 开源人工智能工具

    在这篇文章中 我们将介绍几个顶级的开源Linux生态系统的人工智能 AI 工具 目前 AI是科学和技术中不断进步的领域之一 很多人都在致力于构建软件和硬件来解决诸如医疗 教育 安全 制造业 银行等领域的日常挑战 下面是一系列旨在并开发成用于
  • Win32 API和PE-COFF

    一个熟练的Linux程序员可以写一个程序直接和内核交流 比如通过open或者write函数 在Windows则没有那么幸运了 每个新的安装包和Windows NT的发布 都改变了内核的接口 还有对应的库的集合 DLLs给进程提供了一种方式
  • RedisTemplate lettuce 实现分布式锁

    springboot2 x 以上使用redis时 默认使用了lettuce封装 比起jedis线程安全 import lombok extern slf4j Slf4j import org springframework data red
  • 闭关之 Vulkan 应用开发指南笔记(四):绘制、几何体&片段处理、同步和回读数据

    目录 第8章 绘制 8 1 准备绘制 8 2 顶点数据 8 3 索引绘制 8 3 1 只用索引的绘制 8 3 2 重置索引 8 4 实例化 8 5 间接绘制 第9章 几何体处理 9 1 表面细分 9 1 1 表面细分配置 表面细分模式 控制
  • Python笔记(基本入门函数)

    第一章 快速上手 基础知识 1 3 x y x x y y 注意求余运算符 向下圆整 如果是负数 则更远离0 10 3 10 3 10 3 10 3 十六进制 0x 八进制 0o 十进制 0b 0xAF 175 0o10 8 0b10110
  • 微信小程序获取openid的两种方式

    这篇文章是关于获取openid的两种方式 自己在学着用微信小程序来写一个小东西玩 首先我们要到小程序官网获取到自己的appid和Appsecret 如图 第一种 直接在微信小程序中获取 不需要通过后台 登录 wx login success
  • 【数据库】基础知识扫盲

    一 基础知识 关系型数据库 多张表 各表之间的关系 关系 元祖 属性 元组是关系数据库中的基本概念 关系是一张表 表中的一行 即数据库中的每条记录 就是一个元组 表中的一列就是一个属性 关系 表 元祖 表中的一行 属性 表中的一列 码 由一
  • LeetCode 1108. Defanging an IP Address

    import re class Solution def defangIPaddr self address str gt str 这个简单 正则字符串 替换 return re sub address 提交时间 2019 08 03 16
  • springboot运行原理详解

    文章目录 前言 正文 父依赖 主启动类 SpringBootApplication ComponentScan SpringBootConfiguration EnableAutoConfiguration EnableAutoConfig
  • linux查看、添加、删除环境变量

    阅读目录 一 Linux 环境变量介绍 1 1 Linux 环境变量介绍 1 2 Linux 环境变量分类 1 3 Linux 常用的环境变量 二 Linux 查看环境变量 三 Linux 添加环境变量 3 1 添加系统级环境变量 需roo
  • PCL之区域生长分割

    算法思想 首先依据点的曲率值对点进行排序 之所以排序 是因为区域生长算法是从曲率最小的点开始生长的 这个点就是初始种子点 初始种子点所在的区域即为最平滑的区域 从最平滑的区域开始生长可减少分割片段的总数 提高效率 算法流程 设置一空的种子点
  • 给服务器下载补丁及安装补丁

    近期服务器被管理员扫到存在很多漏洞 1 https support microsoft com en us help 4299875 june 2018 updates for microsoft office 2 https www mi
  • 微软重磅开源 Visual ChatGPT! 一个月内斩获30K star

    点击上方 Github中文社区 关注 看Github 每天提升 第067期分享 github中文社区 大家好 我是Huber 今年由于大环境恶化 为了生活本人这一年在某外企从事某个秘密项目 正经的那种 的研发 所以没有时间 动力 和精力 钱
  • 微软修改 MIT 项目原作者版权声明引发争议;白宫为提高开源安全性邀请软件行业者座谈;Ruby 3.1.0 发布

    整理 宋彤彤 责编 屠敏 开源吞噬世界的趋势下 借助开源软件 基于开源协议 任何人都可以得到项目的源代码 加以学习 修改 甚至是重新分发 关注 开源日报 一文速览国内外今日的开源大事件吧 一分钟速览新闻点 白宫邀请软件行业者座谈 以提高开源
  • Android设备接入阿里云IoT物联网平台

    1 准备工作 1 1 注册阿里云账号 使用个人淘宝账号或手机号 开通阿里云账号 并通过 实名认证 可以用支付宝认证 1 2 免费开通IoT物联网套件 产品官网 https www aliyun com product iot 1 3 软件环
  • 拒绝摆烂!C语言练习打卡第六天

    博客主页 小王又困了 系列专栏 每日一练 人之为学 不日近则日退 感谢大家点赞 收藏 评论 目录 一 选择题 1 第一题 2 第二题 3 第三题 4 第四题 二 编程题 1 第一题 2 第二题 前言 在前面我们学习完C语言的所以知识 当然练
  • 【华为OD机试真题 python】积木最远距离【2022 Q4

    题目描述 积木最远距离 小华和小薇一起通过玩积木游戏学习数学 他们有很多积木 每个积木块上都有一个数字 积木块上的数字可能相同 小华随机拿一些积木挨着排成一排 请小薇找到这排积木中数字相同且所处位置最远的2块积木块 计算他们的距离 小薇请你
  • Java中的反射

    Java中的反射 Java反射是指在运行时动态地获取和操作类的信息 包括类的属性 方法和构造函数等 通过反射机制 我们可以在运行时检查类的信息 并动态创建对象 调用方法和访问属性 而不需要在编译时确定类的具体信息 Java反射机制提供了以下
  • 写一本技术书籍

    作者 董伟明 链接 https zhuanlan zhihu com p 22207407 来源 知乎 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 在过去的8个多月的时间里面 我完成了一本504页的 Python W