吾生也有涯,而知也無涯彩扔。以有涯隨無涯妆档,殆已!已而為知者虫碉,殆而已矣贾惦!
1994年4月20日,中國第一根64K國際專線接入國際互聯(lián)網敦捧,說“想要世界的寶藏么须板?如果想要的話,那就去網上找吧兢卵,我把所有的一切都放在那里习瑰。”于是济蝉,水木清華杰刽、搜狐菠发、網易,等等贺嫂、等等滓鸠,掀起了中國互聯(lián)網的熱潮,大互聯(lián)網時代就此展開第喳。
我的上一篇文章How to build?寫于三月之前糜俗,介紹如何零基礎開始學習PYTHON,那時候我入職兩月曲饱,現(xiàn)在還差一月轉為正式員工悠抹,值此機會,從技術角度剖析一下助理PYTHON工程師的工作扩淀,也讓這篇文章作為入門者的技術指南楔敌,如果你能在每一項技術能力前面打勾,你一定是一名成熟的python web工程師驻谆!
工作范疇
- 具備將產品經理的產品理念快速卵凑、有效的轉化為產品價值的全部技術能力
- 對于產品的生命周期有一定認識,并能夠因此來控制自己代碼的復雜性
- 有開放式工作環(huán)境的素質意識胜臊,具備持續(xù)“學習”的學習能力
工作1:技術能力
1.1 基本能力
軟件工程勺卢,是個很有意思的名字。十八世紀象对,歐洲創(chuàng)造了“工程”一次黑忱,本來含義是有關兵器制造、具有軍事目的的各項勞作勒魔,后擴展到許多領域甫煞,如建筑屋宇、制造機器沥邻、架橋修路等危虱。軟件·工程并無二致,甚至不需要車床吊車等物理硬件唐全,只要會想(敢于類比與聯(lián)想埃跷,讀史使人明智)、會寫(運用編輯器輸入代碼邮利,vim是不錯的選擇)弥雹、會問(靈活的使用Google,科學上網)延届、會生活(與同事搞好關系剪勿,辦公室至少9小時呢)。
當一個程序員方庭,不僅僅是實現(xiàn)功能代碼厕吉,還要有一點美感酱固,就像建房子。如果封裝不優(yōu)雅头朱,房子外表很難看运悲;如果接口不優(yōu)雅,房門都很難進项钮;如果抽象層不優(yōu)雅班眯,房子根本沒法裝修。有一點對“美感”的追求烁巫,對工程的敬畏之心署隘,就像電鋸驚魂中的工程工具(殺人的美學),會讓我們的工作事半功倍亚隙。
1.2 運維能力
說到運維磁餐,就是一種管理的能力,管理計算機系統(tǒng)恃鞋,管理數據庫崖媚,管理應用配置,讓一切都流程化恤浪、標準化并自動化。
- 計算系統(tǒng)肴楷∷桑基于kubernetes寫dockerfile,基于成熟的docker系統(tǒng)創(chuàng)建赛蔫、銷毀容器砂客。DOCKER讓系統(tǒng)自動化
任何系統(tǒng)問題都能用“重啟”的方式解決,如果不行呵恢,那就重啟兩次鞠值。云是大勢,所以只要我們能弄出最基本的系統(tǒng)image渗钉,比如macOS彤恶、阿里云,那么作為程序員的我們就能夠一展身手鳄橘。
當然声离,理解操作系統(tǒng)是很有必要的,不要浪費或過度使用機器性能瘫怜,注重sql語句的優(yōu)化术徊,進程的使用 - 數據庫。DBA讓數據庫自動化
- 應用配置鲸湃。CMDB讓應用自動化
- 生產環(huán)境赠涮。我們要學會利用以上子寓,必要時候開發(fā)以上,學會起docker笋除,學會和DBA溝通别瞭,學會起CMDB,以及學會管理自己的生產環(huán)境株憾!
- 基本cmd命令蝙寨,比如yum,mkdir嗤瞎,touch墙歪,cd,rm贝奇,>虹菲,grep,ps掉瞳,top毕源,w,nohup陕习,set霎褐,crontab等等;
- 基本編輯器vim该镣,會配置使用vim(用vundle來管理插件)冻璃,或者基本ide atom;
- 基本解釋器损合,python環(huán)境管理pipenv省艳,
pipenv install
,pipenv shell
嫁审; - 基本代碼管理git跋炕,pull,push律适,checkout辐烂,rebase
- 基本數據庫管理,mongo擦耀,mysql, els的啟用棉圈,migrate,export眷蜓,import
- 基本業(yè)務管理分瘾,能夠預估開發(fā)feature的時間,能夠管理開發(fā)的輕重緩急,能夠對業(yè)務細節(jié)反復推敲
- 基本個人管理德召,能夠健康白魂,能夠“有愛”
就個人或小組開發(fā)而言,掌握以上應該能讓你非常舒服地做一個開發(fā)工程師上岗,所謂工欲善其事福荸,必先利其器。
1.3 PYTHON能力
說到PYTHON肴掷,很多人都會寫敬锐,語言很簡單,但工程師之間工資又各有不同呆瞻,這是為什么呢台夺?為了回答這個問題,不妨上拉勾網搜索了一下“金主”們對工程師的要求痴脾。
搜索詞為'python'颤介,篩選為工資‘25k-50k’以及‘50k以上’,我隨機選取了第一頁的兩個公司
可是看出,對于‘初級玩家’公司主要看你“會不會”赞赖,也就是0和1的區(qū)別滚朵;而對于‘中級玩家’公司主要看中你“會不會分析,能不能優(yōu)化”前域,也就是1和10的區(qū)別辕近;至于‘高級玩家’,我想只會PYTHON是不行的话侄。那么我的這篇文章亏推,一方面總結一下我半年的學習成果,希望能夠把知識從0到1真正落到實處年堆,便于以后從1到10不斷進步;另一方面盏浇,借著分享交流的互聯(lián)網变丧,希望各位同行能夠指出我工作學習中的短板,幫助我不斷改進绢掰。
1.3.1 Clean Code
我在上篇文章中推薦在HackerRank做完全部python習題痒蓬,并且在LeetCode上繼續(xù)訓練。不斷刷題能極大的增強我們寫單個函數滴劲、算法的能力攻晒,訓練我們的思維能力,但對我們寫"工程項目"卻鮮有幫助班挖。因為每一題的context都不一樣鲁捏,容易養(yǎng)成重復造輪子、代碼不整潔的壞習慣萧芙,在我入職的第一個月给梅,因為壞習慣被反復批評假丧,之后我仔細讀了《Clean Code》一書,情況有所好轉动羽。所以包帚,請務必注意代碼的測試、抽象層运吓、命名規(guī)范渴邦、參數、Exception等拘哨。
訓練方法:《Clean Code》谋梭,要有好代碼的smell
訓練成果:厲害的程序員寫出機器能讀懂的代碼,好的程序員寫出人能讀懂的代碼宅静。
# 保齡球積分章蚣,從第0輪到第10輪,已知每一輪的擊倒情況姨夹,求總分
def score_frame(frame=10):
score = 0
ordinal_ball = 0
for current_frame in range(frame):
if is_strike(ordinal_ball):
score += 10 + next_two_balls_for_strike()
ordinal_ball += 1
elif is_spare(ordinal_ball):
score += 10 + next_ball_for_spare()
ordinal_ball += 2
else:
score += two_balls_in_frame()
ordinal_ball += 2
return score
1.3.2 Flask
整潔代碼是基礎中的基礎纤垂,接下來掌握的是web框架。要想熟練使用Flask磷账,知識上要求對網絡會話層峭沦、表示層和應用層有了解,從Client端輸入URI并發(fā)送請求的一瞬間逃糟,網絡通過自上而下的OSI結構吼鱼,傳輸層(TCP)--- 網絡層(IP) --- 數據鏈路層 --- 物理層, 路由(識別IP)绰咽,然后菇肃,Server端與之建立TCP連接,拿到request對象取募,梳理業(yè)務邏輯琐谤,返回response對象,經過同樣的一系列過程到Client端接受數據(如果是瀏覽器則會渲染頁面)玩敏。這背后所有的事情斗忌,就是一個web工程師的工作所在。
訓練方法:《Flask Web開發(fā)旺聚,基于python的web開發(fā)實戰(zhàn)》织阳,上篇文章已經推薦過了
訓練成果:能夠獨立編寫并部署一個滿足業(yè)務需求的web應用
from flask import Flask, request, jsonify
from models import get_question_analysis
app = Flask(__name__)
@app.route('/', methods=['GET'])
def index():
return 'hello world'
@app.route('/api', methods=['POST'])
def api():
data = request.get_json()
question = data['question']
question_analysis = get_question_analysis(question)
return jsonify(question_analysis)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=False)
1.3.3 AioHttp
一步通,則步步通,能夠學會一個框架惊窖,其他的框架就不難了刽宪。Flask的底層是werkzeuk,基于CGI(通用網關接口界酒,Common Gateway Interface)的WSGI在業(yè)務受到了異步的挑戰(zhàn)圣拄,ASGI應運而生。AioHttp的框架毁欣,支持python asycio庇谆,能極大的提高API的性能(與flask框架下API性能的差異,請移步我的測試文章)凭疮。
訓練方法:AioHttp Git饭耳,Asyncio Doc,永遠不要忘記源碼和doc
訓練成果:能夠獨立編寫并部署一個滿足業(yè)務需求的web應用执解,理解并掌握python的異步語法
from aiohttp import web
from models import get_question_analysis
async def index(request):
return web.Response(text='Hello World')
async def api(request):
data = await request.json()
question = data['question']
question_analysis = await get_question_analysis(question)
return web.json_response(question_analysis)
app = web.Application()
app.add_routes([web.get('/', index),
web.post('/api', api)])
if __name__ == '__main__':
web.run_app(app, host='0.0.0.0', port=5000)
Parallelism introduces new challenges in writing correct code, particularly in the presence of shared, mutable state.
1.3.4 MONGO
對于一個助理工程師寞肖,不懂框架,你也能形成生產力衰腌,可以做一個寫數據庫增刪改查的cool boy新蟆。如果一個工程師不會操作數據庫,那就連“刪庫跑路”的“黑暗森林威懾”都建立不起來...所以無論怎樣右蕊,這個得會琼稻。我們有兩種操作mongodb的方式,一種是ODM(Object-Document Mapper)饶囚,如mongoengine帕翻;另一種則是超有名的pymongo。
訓練方法:MongoEngine文檔萝风,PyMongo文檔
訓練成果:熟練對mongo表進行增刪改查嘀掸,能夠對mongo表查詢進行一定程度的優(yōu)化
# 更改user_info這張表中的user_id為‘test’的年齡為22
# mongoengine
from mongoengine import Document, connect
from config import MONGO_URI
connect(host=MONGO_URI, alias='default')
class UserInfo(Document):
user_id = StringField(required=True)
age = IntField()
UserInfo.objects.get(user_id='test').update(age=22)
# pymongo
from config import MONGO_URI, DB
from pymongo import MongoClient
client = MongoClient(MONGO_URI)
collection = client[DB]['user_info']
collection.update({'user_id': 'test'}, {'age': 22})
簡單分析一下二者的優(yōu)缺點:
- mongoengine允許我們定義一套模式,然后把所有的值都匹配到我們定義的schema上规惰,這種schema更加清楚和明確横殴,個人感覺比字典更容易操作,用dot notation更像OOP卿拴,而pymong返回的是一個dict,操作時困難的多梨与,很多時候有點丑
- mongoengine相當于在你和pymongo之間加了map層堕花,所以會對性能有微乎其微的影響,在進行很簡單的查詢時顯得有些沒有必要
1.3.5 MYSQL
noSQL和SQL的取舍總是要不斷斟酌粥鞋。操作mysql我們也有兩種方式缘挽,ORM的sqlalchemy,以及pymysql
訓練方法:SqlAlchemy文檔,PyMySql文檔
訓練成果:熟練對mysql表進行增刪改查壕曼,能夠對mysql表查詢進行一定程度的優(yōu)化
# 向user_info這張表中存入一條姓名為‘test’苏研,年齡為22的數據
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from config import MYSQL_URI
Base = declarative_base()
engine = create_engine(MYSQL_URI, echo=False)
Session = sessionmaker(bind=engine)
session = Session()
class UserInfo(Base):
__tablename__ = 'user_info'
user_id = Column(String(80), nullable=False)
age = Column(Integer(), nullable=True)
session.add(UserInfo('test', 22))
session.commit()
ORM的用途非常非常廣,使用起來很優(yōu)雅腮郊,但如同flask框架一般摹蘑,深入探究它的使用方法和場景需要大量的篇幅,會在以后的文章中繼續(xù)分享轧飞,希望感興趣的同學自行探索衅鹿,也可以在評論區(qū)有更多交流。
1.3.6 Abstraction
Computer programs consist of instructions to either: Compute some value Or Carry out some action
有了框架和數據庫过咬,剩下的就是“操作”了大渤,也就是業(yè)務邏輯的編寫。如果使用命令式編程掸绞,實現(xiàn)業(yè)務不是一件困難的事情泵三,那么代碼的區(qū)別就彰顯了工程師們的抽象水平。百多行的函數衔掸;沒有層次感的代碼烫幕;命名不規(guī)范的代碼;概率編程具篇;google編程纬霞,等等,不一而足驱显。優(yōu)秀的工程師诗芜,對抽象一定有自己的理解!
訓練方法:多想埃疫,多看
訓練成果:至少能夠從“只看到了”函數伏恐,到“看到了”項目,從細節(jié)到系統(tǒng)
# 表示有理數栓霜,并計算其平方
# 表示方法
def rational(n, d):
return [n, d]
def numerator(x):
return x[0]
def denominator(x):
return x[1]
# 操作方法
def square_rational(x):
return mul_rational(x, x)
def square_rational_violation_once(x):
return rational(numerator(x) * numerator(x), denominator(x) * denominator(x))
def square_rational_violation_twice(x):
return [x[0] * x[0], x[1] * x[1]]
# 表示方法 2
def rational(n, d):
def get(index):
if index == 0:
return n
elif index == 1:
return d
return get
def numerator(x):
return x(0)
def denominator(x):
return x(1)
用了一個簡單的例子來解釋表示層和操作層(完全不一樣的表示層翠桦,但是操作層卻完全一樣),龐大的系統(tǒng)必然存在著細小的抽象胳蛮。我們只要能夠掌握抽象的方法销凑,再配合leetcode中的算法知識,那么所有的業(yè)務邏輯必然迎刃而解仅炊。
1.3.7 lib/site-packages
框架 -> 數據庫 -> 抽象斗幼,我把技術內容分成了這三塊,那其實還有一些邊角料抚垄。python為人稱道的就是大量好用的包蜕窿,所以python工程師經常被說成調包的谋逻。在工作中當然也會直接調包,比如smtp和beautifulsoup桐经,這兩個太常見了毁兆。
import requests
from bs4 import BeautifulSoup
url_head = 'http://www.reibang.com/u/1f167239855b'
HTML = requests.get(url_head).text
soup = BeautifulSoup(HTML, 'lxml')
soup.find_all()
1.3.8 widgets
最后的最后,在項目開發(fā)的過程中阴挣,一定會和公司業(yè)務有聯(lián)系气堕,也一定會發(fā)生很多bug,更會有一些奇奇怪怪的需求屯吊。為了應對各種各樣的事情送巡,python工程師集成了大量好用的工具,比如elastic-search盒卸,sentry骗爆,kafka, memcache等等蔽介,這種Client/Server的構架很好用摘投,也是微服務的雛形。
1.3.9 behave && selenium
OK虹蓄,做完所有工作犀呼,臨近上線,我的PM一定會在旁邊大喊三聲:測試薇组!測試外臂!測試!自動化測試是所有穩(wěn)定系統(tǒng)的標配律胀,unittests和doc tests不必多提宋光,這里介紹一種BDD工具,behave和selenium炭菌。
功能: 自動測試
場景: 頁面點擊
假如 我在登陸頁面
當 輸入賬號罪佳、密碼并點擊登陸
那么 我在個人主頁
from behave import given, when, then
from selenium import webdiver
driver = webdrivear.Chrome(driver_path, chrome_options=chrome_options)
@given('我在登陸頁面')
def login_in(context):
driver.get(login_url)
assert is_at_page(LOGIN_PAGE)
@when('輸入賬號、密碼并點擊登陸')
def send_key(context):
driver.find_element_by_id(ACCOUNT).send_keys(KEYS)
dirver.find_element_by_id(CONFIRM).click()
@then('我在個人主頁')
assert is_at_page(HOME_PAGE)
如果你覺得測試沒有必要黑低,那你一定沒有寫過測試赘艳!
1.3.10 CI && CD
OK,順利通過測試克握,合并到master蕾管,此時應該有一套能夠自動集成、自動部署的機制菩暗,用python起一個監(jiān)控master分支的服務娇掏,一出現(xiàn)合并操作,就使用ssh協(xié)議重啟原服務勋眯。
至此婴梧,整套python web開發(fā)后端流程的技術要點都清晰了,希望以后能夠繼續(xù)成長客蹋、分享塞蹭,也希望閱讀到這里的伙伴多多交流、給予指導讶坯。
1.4 前端能力
互聯(lián)網行業(yè)注重T型人才的培養(yǎng)番电,所謂的T型人才就是橫向了解,縱向發(fā)展辆琅,所以web開發(fā)往往看重全棧的能力漱办。
- HTML。標記性語言婉烟,就用jinja模版吧娩井。
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
CSS。樣式語言似袁,就用bootstrap吧洞辣。
{% extends 'bootstrap/base.html %}
JS。動態(tài)交互昙衅,就用ajax吧扬霜。
$("#botton").on("click",function(){
$.ajax({
url: 'http://www.baidu.com',
type: 'GET',
success: function(data){
};
})
})
如果你不滿足于如此簡單的前端知識,也可以主動將vue框架融合到我們的頁面中而涉。前端語言還是有很多奇技淫巧著瓶,好看的頁面比后端開發(fā)更容易獲得成就感。
1.5 數據能力
但凡python工程師啼县,大都會一點數據分析材原。那我感覺呢,有數據比沒數據強谭羔,用數據驅動的PM比只有PM驅動靠譜华糖。
- 數據提取。
- 從雜亂的打點數據中瘟裸,用技術取出結構化的數據
- 數據分析和挖掘客叉。
- 可以用random forest分析feature
- 可以用OLS直接預測模型
- 還有一些教育上的模型如BKT,IRT
- 數據驅動话告。
- 可視化模型結果兼搏,并寫分析報告
- 數據理解
- 以上所有技術都可以很快學會,無外乎調包調參沙郭,但理解和分析才是重點
- 在不能獨立佛呻、全方面分析問題時,建議先養(yǎng)成科學的思維習慣(不要連貝葉斯都沒搞明白就妄圖進軍數據分析...)
工作2:架構能力
我經驗較少病线,這部分的理解還需要不斷加強吓著,所言也不過拾人牙慧鲤嫡,暫且一放(代碼的經驗、不一樣的設計模式绑莺、業(yè)務生命周期的理解能力)
工作3:學習能力
- Junior Programmer暖眼,想從碼農成長為工程師,要進步纺裁!
- 工作中有很多可以學習的點诫肠,優(yōu)化一段代碼、發(fā)布一個發(fā)送郵件的package欺缘、上coursera課程栋豫,要學習!
- 學習和工作是很辛苦的谚殊,寫了一天代碼頭昏腦脹丧鸯,還要再看兩個小時英文文檔,要勇敢络凿!
終于在周一發(fā)版了骡送,本來告訴自己每周日要發(fā)布一篇文章的,最近熬夜看TI絮记,時間和精力完全跟不上摔踱。算是全面總結了工作中的一些事情吧,比較基礎怨愤,深入鉆研也有些東西派敷,嗯,共勉撰洗,加油篮愉!