字符串推薦用'' 單引號引用
list: List[int] = [1, 2, 3]
for elem in list:
if elem > 1:
print(f'data {elem} > 1') # 這里是format語句,屬于語法糖
else:
print(f'data {elem} < 1')
'''
data 1 < 1
data 2 > 1
data 3 > 1
'''
x = -1
try:
if x < 0:
raise Exception("Sorry, no numbers below zero")
except Exception as err:
print("find err: %s" % err)
'''
find err: Sorry, no numbers below zero
'''
推導式好處: 效率更高,底層是c執行
一共兩種形式:(參考: https://zhuanlan.zhihu.com/p/139621170) , 它主要是輸出是列表(list)
import re
"""
獲取所有的數字
"""
list = ["1", "2", "3", "4", "5", "a", "b", "c"]
print([elem for elem in list if re.match("\\d", elem)])
'''
['1', '2', '3', '4', '5']
'''
"""
獲取所有的字母
"""
print([elem for elem in list if re.match("[a-z]", elem)])
'''
['a', 'b', 'c']
'''
"""
如果元素是數字則存儲,否則則upper
"""
print([elem if re.match("\\d", elem) else elem.upper() for elem in list])
'''
['1', '2', '3', '4', '5', 'A', 'B', 'C']
'''
最佳實踐: 參考(https://github.com/httpie/httpie/blob/master/httpie/core.py#L235)
def decode_raw_args(
args: List[Union[str, bytes]],
stdin_encoding: str
) -> List[str]:
"""
Convert all bytes args to str
by decoding them using stdin encoding.
"""
return [
arg.decode(stdin_encoding)
if type(arg) is bytes else arg
for arg in args
]
def decode_raw_args_parse(
args: List[Union[str, bytes]],
stdin_encoding: str
) -> List[str]:
"""
Convert all bytes args to str
by decoding them using stdin encoding.
不使用推導式
"""
result: List[str] = []
for arg in args:
if type(arg) is bytes:
result.append(arg.decode(stdin_encoding))
else:
result.append(arg)
return result
# arg.decode(stdin_encoding) if type(arg) is bytes else arg for arg in args
print(decode_raw_args(args=[b'111', b'222'], stdin_encoding="utf-8"))
print(decode_raw_args(args=["111", "222"], stdin_encoding=""))
'''
['111', '222']
['111', '222']
'''
print(decode_raw_args_parse(args=[b'111', b'222'], stdin_encoding="utf-8"))
print(decode_raw_args_parse(args=["111", "222"], stdin_encoding=""))
'''
['111', '222']
['111', '222']
'''
{key_expr:value_exprforvalueincollectionifcondition} ,輸出是dict
"""
{ key_expr: value_expr for value in collection if condition }
反轉key value,且獲取 value 為在set {'a', 'b', 'c'}中的元素
"""
dict_old = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}
print({dict_old[value]: value for value in dict_old if value in {'a', 'b', 'c'}})
'''
{'A': 'a', 'B': 'b', 'C': 'c'}
'''
print({key: value for value, key in dict_old.items() if value in {'a', 'b', 'c'}})
'''
{'A': 'a', 'B': 'b', 'C': 'c'}
'''
表達式:
其實就是上面列表推導式[] 換成{} ,輸出由list 變成了set
import os
from collections.abc import Iterable
with open("text.log", "wt") as file:
file.truncate()
file.writelines("line 1" + os.linesep)
file.writelines("line 2" + os.linesep)
file.writelines("line 3" + os.linesep)
pass
with open("text.log", "rt") as file:
for line in file:
print("type: {type}, isinstance: {isinstance}, line: {line}".format(type=type(file),
isinstance=isinstance(file, Iterable),
line=line))
pass
'''
type: <class '_io.TextIOWrapper'>, isinstance: True, line: line 1
type: <class '_io.TextIOWrapper'>, isinstance: True, line: line 2
type: <class '_io.TextIOWrapper'>, isinstance: True, line: line 3
'''
這里面_io.TextIOWrapper 實現了 __next__() 方法
比如我們自己實現一個可迭代的對象
下面可以看到我使用了類型申明List[str] 其實這個python運行時并不會檢測,需要工具進行檢測!
變量默認都是Any 類型 ,具體可以看 https://docs.python.org/zh-cn/3/library/typing.html
from typing import List
class Items(object):
def __init__(self, list: List[str]):
self.list = list
self.index = 0
def __next__(self, *args, **kwargs):
"""
next,沒有拋出StopIteration
"""
if self.index >= len(self.list):
raise StopIteration
result = self.list[self.index]
self.index = self.index + 1
return result
def __iter__(self, *args, **kwargs):
"""
返回一個迭代器
"""
return self
data = Items(["1", "2", "3"])
for x in data:
print(x)
'''
1
2
3
'''
from ..a import foo # 上級目錄
from .a import foo_a # 當前目錄
import sys # 引用源碼或者lib
from copy import deepcopy # 引用源碼或者lib
from pygments.formatters.terminal import TerminalFormatter # 引用 lib.lib.file
import demo.utils.a
def c_foo():
demo.utils.a.foo_a()
TerminalFormatter()
deepcopy()
print(sys.api_version)
def b_foo():
foo()
Text Type: | str |
Numeric Types: | int,float,complex |
Sequence Types: | list,tuple,range |
Mapping Type: | dict |
Set Types: | set,frozenset |
Boolean Type: | bool |
Binary Types: | bytes,bytearray,memoryview |
x = 1 # int
y = 1.1 # float
z = 1j # 復數(complex)
a = complex(1, 2) # 復數(complex)
print(type(x))
print(type(y))
print(type(z))
print(z.imag, z.real)
print(type(a))
print(a.imag, a.real)
'''
<class 'int'>
<class 'float'>
<class 'complex'>
1.0 0.0
<class 'complex'>
2.0 1.0
'''
str = "hello"
print(str)
print(str[0:])
print(str[:5])
print(str[:-1])
print(str[0:5])
print(str[0:5:1])
print(str[0:5:2])
'''
hello
hello
hello
hell
hello
hello
hlo
'''
# format
print("My name is {} and age is {}".format("tom", 18))
'''
My name is tom and age is 18
'''
quantity = 3
itemno = 567
price = 49.95
myorder = "I want to pay {2} dollars for {0} pieces of item {1}."
print(myorder.format(quantity, itemno, price))
'''
I want to pay 49.95 dollars for 3 pieces of item 567.
'''
# func
str = "hello world! "
print(str.upper())
print(str.lower())
print(str.strip())
print(str + " ...")
'''
HELLO WORLD!
hello world!
hello world!
hello world! ...
'''
# format
myorder = "I have a {carname}, it is a {model}."
print(myorder.format(carname="Ford", model="Mustang"))
'''
I have a Ford, it is a Mustang.
'''
其實就是一個func
def add(num):
return lambda x: x + num
print(add(10)(10))
'''
20
'''
lanbda 例子2
import json
class Obj:
def __init__(self):
self.name = "tom"
self.age = 1
print(json.dumps(Obj(), default=lambda obj: obj.__dict__))
'''
{"name": "tom", "age": 1}
'''
list,tuple,range,dict,set,frozenset
mylist = ["apple", "banana", "cherry"]
# 切片
print(mylist[0])
print(mylist[2])
print(mylist[-1])
print(mylist[0:3:2])
'''
apple
cherry
cherry
['apple', 'cherry']
'''
# 基本操作
mylist.append("orange")
print(mylist)
'''
['apple', 'banana', 'cherry', 'orange']
'''
mylist.insert(0, "mango")
print(mylist)
'''
['mango', 'apple', 'banana', 'cherry', 'orange']
'''
# 循環
for x in mylist:
print(x)
'''
apple
banana
cherry
orange
'''
for index in range(len(mylist)):
print("index: %d" % index)
'''
index: 0
index: 1
index: 2
index: 3
index: 4
'''
if "apple" in mylist:
print("success!")
'''
success!
'''
# [執行表達式(也就是for循環中的,如果有if則是if中執行的), for item in list 條件表達式]
new_list = [elem.upper() for elem in mylist if "a" in elem] # contains 'a' char elem str
print(new_list)
'''
['MANGO', 'APPLE', 'BANANA', 'ORANGE']
'''
newList = []
for elem in mylist:
if 'a' in elem:
newList.append(elem.upper())
print(newList)
'''
['MANGO', 'APPLE', 'BANANA', 'ORANGE']
'''
thisdict = {"brand": "Ford", "model": "Mustang", "year": 1964}
for key, value in thisdict.items():
print("key: {}, value: {}".format(key, value))
'''
key: brand, value: Ford
key: model, value: Mustang
key: year, value: 1964
'''
for key in thisdict:
print("key: {}, value: {}".format(key, thisdict[key]))
'''
key: brand, value: Ford
key: model, value: Mustang
key: year, value: 1964
'''
# range 會生成一個迭代器,(start,end,sep) , 左閉右開
for x in range(6): # [0,1,2,3,4,5]
print("x is %d" % x)
'''
x is 0
x is 1
x is 2
x is 3
x is 4
x is 5
'''
for x in range(2, 6):
print("x is %d" % x)
'''
x is 2
x is 3
x is 4
x is 5
'''
for x in range(1, 6, 2):
print("x is %d" % x)
'''
x is 1
x is 3
x is 5
'''
def func_1():
pass # 空方法必須申明pass
func_1()
# name 為必須添的參數,不然為空會報錯
# age 為默認參數
# agrs 為可變參數
# kwargs 為 k v 參數
def func_1(name, age=1, *args, **kwargs):
print("name: %s" % name)
print("age: %d" % age)
print("len(args): {}, type: {}".format(len(args), type(args)))
for value in args:
print("args value: {}".format(value))
print("len(kwargs): {}, type: {}".format(len(kwargs), type(kwargs)))
for key, value in kwargs.items():
print("kwargs key: {}, value: {}".format(key, value))
func_1(name="tom", age=10, args="1", kwargs="2")
'''
name: tom
age: 10
len(args): 0
len(kwargs): 0, type: <class 'tuple'>
len(kwargs): 2, type: <class 'dict'>
kwargs key: args, value: 1
kwargs key: kwargs, value: 2
'''
# 這里注意由于dict所以不能申明kv
func_1("tom", 10, "1", "2", args="1", kwargs="2")
'''
name: tom
age: 10
len(args): 2, type: <class 'tuple'>
args value: 1
args value: 2
len(kwargs): 2, type: <class 'dict'>
kwargs key: args, value: 1
kwargs key: kwargs, value: 2
'''
申明輸入輸出類型
from typing import List, Union
def decode_raw_args(
args: List[Union[str, bytes]],
stdin_encoding: str
) -> List[str]:
"""
Convert all bytes args to str
by decoding them using stdin encoding.
"""
return [
arg.decode(stdin_encoding)
if type(arg) is bytes else arg
for arg in args
]
# 如果沒有父類繼承,這里選擇 object,比較規范
class Person(object):
# gender none, male or female
gender = "none"
# 構造器
def __init__(self, name, age):
self.name = name
self.age = age
def my_name(self):
return self.name
p = Person(name="tome", age=1)
print(p.my_name())
import json
class Person(object):
# gender none, male or female
gender = "none"
# 構造器
def __init__(self, name, age):
self.name = name
self.age = age
def my_name(self):
return self.name
p = Person(name="tome", age=1)
print(p.my_name())
class Mail(Person):
def __init__(self, name, age):
super(Mail, self).__init__(name, age)
self.gender = "mail"
def my_name(self):
return self.name + "_mail"
p = Mail(name="tome", age=1)
print(json.dumps(p, default=lambda obj: obj.__dict__))
print(p.my_name())
主要是__init__執行前會調用
#!/usr/bin/python
import json
class Person(object):
def __new__(cls, *args, **kwargs):
instance = object.__new__(cls)
instance.job = "it"
return instance
# construct
def __init__(self, name, age):
self.name = name
self.age = age
def to_json(self):
return json.dumps(self, default=lambda obj: obj.__dict__)
p = Person(name="tome", age=1)
print(p.to_json()) # {"age": 1, "job": "it", "name": "tome"}
if type(1) is int:
print("args is int")
... # 等效 pass
'''
args is int
'''
可以參考文件: https://segmentfault.com/q/1010000010389542 , 屬于doctest
def humanize_bytes(n, precision=2):
# Author: Doug Latornell
# Licence: MIT
# URL: https://code.activestate.com/recipes/577081/
"""Return a humanized string representation of a number of bytes.
>>> humanize_bytes(1)
'1 B'
>>> humanize_bytes(1024, precision=1)
'1.0 kB'
>>> humanize_bytes(1024 * 123, precision=1)
'123.0 kB'
>>> humanize_bytes(1024 * 12342, precision=1)
'12.1 MB'
>>> humanize_bytes(1024 * 12342, precision=2)
'12.05 MB'
>>> humanize_bytes(1024 * 1234, precision=2)
'1.21 MB'
>>> humanize_bytes(1024 * 1234 * 1111, precision=2)
'1.31 GB'
>>> humanize_bytes(1024 * 1234 * 1111, precision=1)
'1.3 GB'
"""
abbrevs = [
(1 << 50, 'PB'),
(1 << 40, 'TB'),
(1 << 30, 'GB'),
(1 << 20, 'MB'),
(1 << 10, 'kB'),
(1, 'B')
]
if n == 1:
return '1 B'
for factor, suffix in abbrevs:
if n >= factor:
break
# noinspection PyUnboundLocalVariable
return f'{n / factor:.{precision}f} {suffix}'
其實類似于程序的斷電,比如程序運行到那里其實是返回一個生成器,然后當你下一步是才會執行,比較節省內存
from typing import List
def new(size: int = 1024 * 1024):
yield new_data(size)
def new_data(size: int) -> List[int]:
return [0] * size
data = new()
print(type(data))
print(len(next(data))) # 只能執行一次 next不然報錯
'''
<class 'generator'>
1048576
'''
echo "aGVsbG8gcHl0aG9uCg==" | python -c "import sys,base64; print(sys.stdin.read())"
->
echo "aGVsbG8gcHl0aG9uCg==" | python -c "import sys,base64; print(base64.b64decode(sys.stdin.read()))"
-> stdout:
b'hello python\n'
第一列可以和第二列文件類型組合,第一列不允許并存
import os
with open("file.log", "w") as file:
for x in range(0, 100):
file.write("hello world"+os.linesep)
with open("file.log","r") as file:
for line in file.readlines():
print(line)
import json
print(json.dumps({"k1": "v1", "k2": [1, 2, 3]}))
print(json.loads('{"k1": "v1", "k2": [1, 2, 3]}'))
如果是class,需要繼承JSONEncoder和JSONDecoder實現子類 ,或者
import json, datetime
class Demo(object):
def __init__(self, name: str, age: int, birthday: datetime.date):
self.name = name
self.agw = age
self.birthday = birthday
def to_json(self, _):
return {"name": self.name, "age": self.agw, "birthday": self.birthday.strftime("%Y-%m-%d")}
data = Demo("tom", 18, datetime.date(2001, 1, 1))
print(json.dumps(data, default=data.to_json))
官方文檔: https://docs.python.org/zh-cn/3/library/typing.html
可以參考這篇文章: https://sikasjc.github.io/2018/07/14/type-hint-in-python/
對于喜歡靜態類型的語言,我覺得是非常nice的
應上篇,續講前文。今天咱來聊一下Dockerfile的使用 。
雖然可以通過docker commit命令來手動創建鏡像,但是通過Dockerfile文件,可以幫助我們自動創建鏡像,并且能夠自定義創建過程。本質上,Dockerfile就是一系列命令和參數構成的腳本,這些命令應用于基礎鏡像并最終創建一個新的鏡像,簡化了從頭到尾的構建流程并極大地簡化了部署工作。
使用Dockerfile的優點:
一、Dockerfile構建鏡像步驟
1、創建Dockerfile文件,名字就是Dockerfile
2、docker build Dockerfile所在路徑 -t 鏡像名稱[:tag]
二、Dockerfile指令
1、FORM
FORM指令是最重要的一個且必須為Dockerfile文件開篇的第一個非注釋行,用于為映像文件構建過程指定基準鏡像,后續的指令運行于此基準鏡像所提供的運行環境。
基準鏡像可以是任務可用鏡像文件,默認情況下,docker build會在docker主機上查找指定的鏡像文件,如果不存在,則會從Docker Hub Registry上拉取所需的鏡像文件。
也就是說,任何新建鏡像必須基于已有的鏡像進行構建。
格式:FROM 鏡像名稱[:tag]
例如:FROM ngxin
2、MAINTAINER
用于讓Dockerfile制作者提供本人的詳細信息,此指令位置不限,但推薦放置FROM之后。
格式:MAINTAINER 作者信息
例如:MAINTAINER "lsy"
3、LABLE
為鏡像指定標簽,會繼承基礎鏡像的LABLE,如果key相同,則覆蓋??商娲鶰AINTANIER使用。
格式:LABLE key1=value1 key2=value2
例如:LABLE author=lsy
4、RUN
指定要運行并捕獲到新容器鏡像中的命令,包括安裝文件、創建文件等,在容器創建過程中執行。
格式 :RUN 指令1 [&& 指令2]
注意:由于Dockerfile中每一個指令都會創建一層,所有層一起構成新的鏡像。如果指令過多的話,會變得很臃腫,增加構建時間,所以可以將指令合并執行
例如:RUN mkdir -p /usr/lsy && echo 'this is lsy file' > /usr/lsy/lsy.html
例如下面這個Dockerfile文件:
基于nginx創建一個鏡像,并創建/usr/lsy目錄并創建lsy.html文件
FROM nginx
MAINTAINER "lsy"
RUN mkdir -p /usr/lsy && echo 'this is lsy file' > /usr/lsy/lsy.html
使用命令進行構建
docker build ./ -t my_nginx_1:v1.1
可以看到,docker會一層層的進行構建。
啟動鏡像:
docker run --rm --name my_nginx_1 -it my_nginx_1:v1.1 /bin/bash
可以看到,容器中確實是執行了RUN指令。
5、COPY
將宿主機的文件或者目錄拷貝到容器的文件系統中,需相對于Dockerfile的路徑。
格式:COPY <src> <dest>
文件復制準則:
例如:把Dockerfile同目錄的test.html文件拷貝到容器中的/usr/lsy目錄中
FROM nginx
MAINTAINER "lsy"
RUN mkdir -p /usr/lsy && echo 'this is lsy file' > /usr/lsy/lsy.html
COPY ./test.html /usr/lsy
使用docker build對Dockerfile進行構建:
啟動容器查看文件是否已拷貝:
6、ADD
功能與COPY類似,還可以使用url規范從遠程位置復制到容器中
格式 :ADD <source> <dest>
例如:ADD ./test.html /usr/lsy
ADD https://www.python.org/ftp/python/3.5.1/python-3.5.1.exe /temp/python-3.5.1.exe
7、WORKDIR
用于為其他Dockerfile指令(如 RUN、CMD)設置一個工作目錄,并且還設置用于運行容器映像實例的工作目錄。WORKDIR之后的指令都會基于設定的工作目錄中運行。
格式:WORKDIR 路徑
例如:將/usr/lsy設置為工作目錄,然后在目錄中創建一個a.html文件
FROM nginx
MAINTAINER "lsy"
RUN mkdir -p /usr/lsy
WORKDIR /usr/lsy
RUN touch a.html
使用docker build創建鏡像
運行容器查看:
可以看到,進來容器就是在工作目錄中,并且目錄中有了需要創建的文件。
8、CMD
類似于RUN指令,CMD指令也可用于運行任何命令或應用程序,不過,兩者的運行時間不同。
RUN指令運行于 鏡像創建過程中,而CMD指令運行于基于Dockerfile構建出的鏡像啟動一個容器時。
CMD指令的目的在于為啟動的容器指定默認要運行的程序,且其運行結束后,容器也將終止,不過CMD指令可以被docker run的命令行參數所覆蓋。
Dockerfile中可以指定多個CMD命令,但只有最后一個才會生效。
格式:CMD <command>
CMD ['<executable>','<param1>','<param2>']
CMD ['<param1>','<param2>']
前兩種語法跟RUN一樣
第三種是用于為ENTERPOINT指令提供默認參數。
例如:CMD c:\Apache24\bin\httpd.exe -w
CMD ['/bin/bash','-c','c:\Apache24\bin\httpd.exe','-w']
9、ENTERPOINT
配置容器啟動后執行的命令,并且不可被 docker run 提供的參數覆蓋。每個 Dockerfile 中只能有一個ENTRYPOINT,當指定多個時,只有最后一個起效。如果有CMD,則CMD的命令被當作參數傳遞給ENTERPOINT。
不過,docker run命令的--entrypoint選項的參數可以對Dockerfile中的ENTRYPOINT進行覆蓋。
Dockerfile中可存在多個 ENTRYPOINT指令,但只有最后一個 才會執行。
格式:ENTRYPOINT <command>
ENTRYPOINT ['<executable>','<param1>','<param2>']
10、ENV
用于為鏡像定義所需的環境變量,并可被Dockerfile文件中位于其后的其他指令所調用。
調用格式為${variable_name}或$variable_name
格式:ENV key1=value1 key2=value2
ENV key value
11、ARG
構建參數,作用于ENV相同,不同的是ARG的參數只在構建鏡像的時候起作用,也就是docker build的時候。
格式:ARG k=v
12、EXPOSE
用來指定端口,是容器內的應用可以通過端口與外界交互
作用跟docker run 命令中的 -p 一樣
格式:EXPOSE 端口
例如:EXPOSE 80
13、VOLUME
用于在鏡像中創建一個掛載點目錄,以掛載Docker Host上的卷或其他容器上的卷
如果掛載點目錄路徑下此前的文件存在,docker run命令會在卷掛載完之后將此前的所有文件 復制到新掛載的卷中。
格式:VOLUME <路徑>
VOLUME ["<路徑1>", "<路徑2>"...]
14、USER
用于執行后續命令的用戶和用戶組
格式 :USER 用戶名[:用戶組]
例如:USER root:root
15、HEALTHCHECK
用于指定某個程序或者指令來監控 docker 容器服務的運行狀態。
格式:HEALTHCHECK [OPTIONS] CMD command
HEALTHCHECK NONE
第一個的功能是在容器內部運行一個命令來檢查容器的健康狀況
第二個的功能是在基礎鏡像中取消健康檢查命令
[OPTIONS]的選項支持以下三中選項:
--interval=DURATION 兩次檢查默認的時間間隔為30秒
--timeout=DURATION 健康檢查命令運行超時時長,默認30秒
--retries=N 當連續失敗指定次數后,則容器被認為是不健康的,狀態為unhealthy,默認次數是3
--start-period=DURATION 容器啟動后多長時間開始執行,默認是0s
注意:
HEALTHCHECK命令只能出現一次,如果出現了多次,只有最后一個生效。
CMD后邊的命令的返回值決定了本次健康檢查是否成功,具體的返回值如下:
0: success - 表示容器是健康的
1: unhealthy - 表示容器已經不能工作了
2: reserved - 保留值
例如:定時 30s PING一下百度,如果PING失敗,則返回1
FROM nginx
MAINTAINER "lsy"
HEALTHCHECK --timeout=3s \
CMD curl -f http://localhost/ || exit 1
使用docker build構建鏡像
運行容器,查看日志輸出:
16、ONBUILD
用于延遲構建命令的執行。簡單的說,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次構建鏡像的過程中不會執行(假設鏡像為 test-build)。當有新的 Dockerfile 使用了之前構建的鏡像 FROM test-build ,這是執行新鏡像的 Dockerfile 構建時候,會執行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
格式 :ONBUILD <其它指令>
17、STOPSIGNAL
當容器退出時給系統發送什么樣的指令
格式:STOPSIGNAL 指令
===============================
我是Liusy,一個喜歡健身的程序員。
獲取更多干貨以及最新消息,請關注公眾號:上古偽神
如果對您有幫助,點個關注就是對我最大的支持!??!
使用Python進行Web開發,你需要掌握一系列關鍵的知識和技能。以下是一份涵蓋基本和進階方面的學習清單:
基礎知識:
1、Python基礎:
對Python語言的基本語法、數據類型、控制流程等有清晰的理解。
2、HTML和CSS:
掌握HTML(超文本標記語言)和CSS(層疊樣式表),用于創建和美化網頁。
3、JavaScript:
了解JavaScript,它是用于在網頁上添加交互性和動態特效的腳本語言。
4、Web協議和網絡基礎:
了解HTTP/HTTPS協議,以及網絡通信的基本原理。
5、前端框架:
學習至少一個前端框架,如React、Vue.js或Angular,用于構建動態、響應式的用戶界面。
后端知識:
1、Web框架:
掌握Python的Web框架,例如Django、Flask或FastAPI。這些框架提供了一系列工具和模塊,加速Web應用的開發。
2、模板引擎:
了解并使用模板引擎(如Jinja2),用于在服務器端生成動態的HTML頁面。
3、數據庫:
學習使用數據庫,理解SQL語言,以及如何在Web應用中進行數據庫操作。常見的數據庫包括MySQL、PostgreSQL、SQLite等。
4、ORM(對象關系映射):
了解并使用ORM框架(例如Django的ORM或SQLAlchemy),簡化與數據庫的交互。
5、RESTful API設計:
學習設計和實現RESTful API,使你的應用可以通過API與其他系統進行通信。
安全性和性能優化:
1、安全性:
了解Web應用的常見安全問題,學習如何防范跨站腳本攻擊(XSS)、跨站請求偽造(CSRF)等攻擊。
2、身份驗證和授權:
學習如何實現用戶身份驗證和授權機制,確保應用的安全性。
3、性能優化:
了解如何優化數據庫查詢、前端資源加載,以及使用緩存和CDN等技術提升應用性能。
版本控制和協作:
1、Git:
學習使用Git進行版本控制,以便有效地協作和管理代碼。
2、團隊協作:
了解團隊協作工具,如GitHub、GitLab等,以便與其他開發者協同工作。
部署和運維:
1、服務器和部署:
了解Web服務器的基本原理,學習如何在服務器上部署Python應用。熟悉常見的部署工具,如Docker、Nginx等。
2、日志和監控:
學習記錄和監控應用的技術,以便及時發現和解決問題。
3、自動化:
掌握自動化部署和測試的工具,如Jenkins、Travis CI等。
測試:
1、單元測試和集成測試:
學習編寫和運行單元測試和集成測試,確保代碼的質量和穩定性。
2、前端測試:
了解前端測試框架,如Jest、Testing Library等,用于測試前端組件和交互。
以上清單涵蓋了Python Web開發的基本要素,你可以根據具體項目需求和興趣深入學習相關的技術。實際項目和不斷的實踐也是鞏固這些知識的重要途徑。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。