Skip to content

Python基础语法

Python 运维脚本常用于处理分支逻辑、循环任务、异常和结构化数据,基础语法覆盖变量、类型、条件、循环、函数和脚本入口。

一、运行脚本

Python 3 是标准。老系统上可能还有 Python 2 遗留,写脚本时确认实际命令指向。

bash
uv run python script.py

如果是服务器环境没有 uv,再按机器上的实际情况用 python3 script.py。本地默认还是走 uv,避免不同 Python 环境混在一起。

python
#!/usr/bin/env python3
# 上面这行让系统知道用 python3 执行,chmod +x 之后可以 ./script.py

print("hello")

交互模式 python3 可以临时验证语法,但运维脚本写成文件更常见。

二、变量与类型

Python 不需要声明类型,赋值即定义。

python
name = "nginx"       # str
port = 80            # int
rate = 3.14          # float
enabled = True       # bool
result = None        # NoneType,表示"空"或"未赋值"

type() 可以查看变量类型,调试时偶尔用。

python
print(type(port))    # <class 'int'>

变量名用小写加下划线(snake_case)。运维脚本通常会传给别人维护,命名规整一点,后面回来看少猜一次。

三、字符串

运维脚本里字符串用得最多,拼路径、拼命令、拼日志。

3.1 f-string

Python 3.6+ 支持 f-string,可以在字符串里嵌变量。

python
service = "nginx"
port = 80

msg = f"{service} is running on port {port}"
print(msg)  # nginx is running on port 80

花括号里可以放表达式:

python
count = 5
print(f"retry count: {count + 1}")  # retry count: 6

老代码里可能见到 .format()% 格式化,功能一样,只是写法旧。

3.2 常用方法

python
s = "  Hello, World!  "

s.strip()           # 去首尾空白,处理用户输入时必用
s.lower()           # "  hello, world!  "
s.upper()           # "  HELLO, WORLD!  "
s.split(",")        # ['  Hello', ' World!  '],按逗号切分
s.replace("World", "Python")  # 替换

"nginx".startswith("ng")      # True
"script.py".endswith(".py")   # True

3.3 多行字符串

python
log = """2024-01-01 12:00:00 INFO  nginx started
2024-01-01 12:00:01 ERROR disk full"""

# 三引号保留换行,适合处理日志或写多行配置

四、运算符

算术和比较跟其他语言基本一样,记几个 Python 特有的。

python
# 算术
10 // 3    # 3,整除(向下取整)
10 % 3     # 1,取余
2 ** 3     # 8,幂运算

# 比较
1 == 1     # True
1 != 2     # True

# 逻辑
True and False   # False
True or False    # True
not True         # False

# 成员判断,运维里常用
"nginx" in ["nginx", "mysql", "redis"]   # True
"php" not in ["nginx", "mysql"]          # True

五、条件判断

if / elif / else,注意用缩进而不是花括号。

python
cpu_usage = 85

if cpu_usage >= 90:
    status = "critical"
elif cpu_usage >= 70:
    status = "warning"
else:
    status = "ok"

print(f"CPU: {cpu_usage}%, status: {status}")

条件可以是任意表达式,Python 里 0""[]None 都算 False

python
result = None

if not result:
    print("result is empty")  # 会执行

多个条件组合:

python
if cpu_usage > 80 and disk_usage > 90:
    print("需要处理")

三元表达式,简单判断可以一行写:

python
level = "high" if cpu_usage > 80 else "normal"

六、循环

6.1 for 循环

遍历列表是运维脚本最常见的用法。

python
services = ["nginx", "mysql", "redis"]

for svc in services:
    print(f"checking {svc}")

range() 生成数字序列:

python
for i in range(5):        # 0, 1, 2, 3, 4
    print(i)

for i in range(1, 6):     # 1, 2, 3, 4, 5
    print(i)

遍历字典时拿到 key 和 value:

python
config = {"host": "10.0.0.1", "port": 3306, "user": "root"}

for key, value in config.items():
    print(f"{key} = {value}")

enumerate() 同时拿到索引和值:

python
for i, svc in enumerate(services):
    print(f"{i}: {svc}")

6.2 while 循环

适合不确定次数的场景,比如重试。

python
import time

retry = 0
max_retry = 3

while retry < max_retry:
    print(f"attempt {retry + 1}")
    # 这里放实际的连接/检查逻辑
    retry += 1
    time.sleep(1)

6.3 break 和 continue

break 跳出循环,continue 跳过本次。

python
for svc in services:
    if svc == "mysql":
        continue  # 跳过 mysql
    print(f"checking {svc}")

七、函数

def 定义,return 返回值。

python
def check_port(host, port):
    """检查端口是否可达"""
    import socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(2)
    result = sock.connect_ex((host, port))
    sock.close()
    return result == 0  # 返回 True/False

if check_port("127.0.0.1", 22):
    print("SSH OK")

7.1 默认参数

python
def run_cmd(cmd, timeout=30, verbose=False):
    """timeout 给默认值 30 秒,调用时可以不传"""
    print(f"running: {cmd}, timeout: {timeout}")
    if verbose:
        print("verbose mode on")

run_cmd("uptime")                    # timeout=30, verbose=False
run_cmd("df -h", timeout=60)         # verbose 仍然是 False
run_cmd("ls", verbose=True)          # timeout 仍然是 30

7.2 *args 和 **kwargs

不确定参数个数时用。

python
def log(level, *tags, **extra):
    # *tags 收集为元组,**extra 收集为字典
    tag_str = ",".join(tags)
    print(f"[{level}] {tag_str} {extra}")

log("ERROR", "nginx", "disk", node="web01", region="cn")
# [ERROR] nginx,disk {'node': 'web01', 'region': 'cn'}

7.3 返回多个值

Python 函数可以返回元组,解构赋值。

python
def get_disk_usage(mount_point):
    import shutil
    total, used, free = shutil.disk_usage(mount_point)
    return total, used, free

total, used, free = get_disk_usage("/")
print(f"used: {used // (1024**3)} GB")

八、异常处理

脚本跑线上出错不能只留一屏堆栈。try / except 至少要把错误位置和原因打清楚。

python
try:
    result = 10 / 0
except ZeroDivisionError as e:
    print(f"error: {e}")

捕获多种异常:

python
try:
    with open("/etc/hosts") as f:
        data = f.read()
    num = int(data)
except FileNotFoundError:
    print("file not found")
except ValueError:
    print("cannot convert to int")

捕获所有异常(谨慎用,可能吞掉有用的报错):

python
try:
    risky_operation()
except Exception as e:
    print(f"unexpected error: {e}")

finally 无论如何都会执行,适合清理资源:

python
conn = None
try:
    conn = get_connection()
    do_something(conn)
except Exception as e:
    print(f"error: {e}")
finally:
    if conn:
        conn.close()  # 不管成功失败都关连接

else 子句:没有异常时才执行。

python
try:
    value = int("42")
except ValueError:
    print("parse failed")
else:
    print(f"parsed: {value}")  # 没异常才到这里

主动抛异常,写工具函数时偶尔用:

python
def validate_port(port):
    if not (1 <= port <= 65535):
        raise ValueError(f"invalid port: {port}")

九、退出码

运维脚本需要返回退出码给 shell,sys.exit()

python
import sys

def main():
    if not check_service():
        print("service check failed", file=sys.stderr)
        sys.exit(1)  # 非零退出码表示失败,shell 判断 $? 时用
    print("all good")
    sys.exit(0)      # 零表示正常

main()

没有 sys.exit() 的话,脚本跑完退出码是 0。但显式写出来更清楚,尤其是脚本有多条执行路径时。

十、注释与文档字符串

单行注释用 #

python
# 跳过已经处理过的文件
if filename in processed:
    continue

函数的 docstring 用三引号,写清楚参数和返回值,IDE 和 help() 能读到:

python
def parse_log_line(line):
    """解析一行日志,返回 (timestamp, level, message) 元组"""
    parts = line.strip().split(None, 2)  # None 表示按任意空白分割,最多分 3 段
    if len(parts) < 3:
        return None
    return parts[0], parts[1], parts[2]