You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python多线程递增写入文件及端口扫描丢行问题求解

问题解答

1. 多线程向单个文件递增写入数字的实现

多线程写入同一文件的核心是避免竞态条件(多个线程同时写文件导致内容覆盖、乱序),可以通过threading.Lock线程锁保证同一时间只有一个线程操作文件。

示例代码:

import threading

# 创建全局锁,控制文件写入权限
file_lock = threading.Lock()

def write_number(num):
    # 自动获取/释放锁,确保写入操作独占
    with file_lock:
        with open("numbers.txt", "a", encoding="utf-8") as f:
            f.write(f"{num}\n")

def main():
    threads = []
    # 启动100个线程,分别写入1-100
    for i in range(1, 101):
        t = threading.Thread(target=write_number, args=(i,))
        threads.append(t)
        t.start()
    # 等待所有线程执行完毕
    for t in threads:
        t.join()

if __name__ == "__main__":
    main()

2. 多线程端口扫描记录不全的问题解决

需求可行性

完全可行,问题出在你代码中的几个关键bug,导致部分端口未被扫描或记录。

代码问题分析

  1. 代码1的致命问题:
    • 异常处理中使用sys.exit():单个线程触发socket.timeout或socket.gaierror时,会直接终止整个进程,导致后续未执行的线程全部停止,这是记录数不足的核心原因。
    • 设置了守护线程(t.daemon = True):若主进程提前结束,未完成的守护线程会被强制终止,导致任务中断。
  2. 代码2的致命问题:
    • 子线程数量计算错误:number_of_sub_threads = port - final_port会得到负数,导致range(port, port + number_of_sub_threads)循环无法执行,漏掉最后一批端口。

正确实现方案

以下是修复后的完整代码,确保1000个端口全部被扫描并记录:

import socket
import threading
import sys

# 文件写入锁,避免多线程写入冲突
file_lock = threading.Lock()

def check_port(ip_host, port):
    try:
        my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
        my_socket.settimeout(5)
        result = my_socket.connect_ex((ip_host, port))
        
        # 加锁写入,保证文件操作安全
        with file_lock:
            with open("./ports.txt", "a+", encoding="utf-8") as f:
                if result == 0:
                    f.write(f"Port {port} is open.\n")
                else:
                    f.write(f"Port {port} is closed.\n")
        my_socket.close()
    except socket.timeout:
        # 仅打印错误,不终止整个进程
        print(f"Timeout on port {port}!")
    except socket.gaierror:
        print(f"Host error when checking port {port}!")
    except KeyboardInterrupt:
        print("Exiting program!")
        sys.exit()

def check_range_ports(ip_host, initial_port, final_port):
    threads = []
    batch_size = 100  # 每批次启动100个线程
    current_port = initial_port

    while current_port <= final_port:
        # 计算当前批次的结束端口,避免超出范围
        end_port = min(current_port + batch_size - 1, final_port)
        # 启动当前批次的线程
        for port in range(current_port, end_port + 1):
            t = threading.Thread(target=check_port, args=(ip_host, port))
            threads.append(t)
            t.start()
        # 等待当前批次所有线程完成
        for t in threads:
            t.join()
        # 重置线程列表,进入下一批次
        threads = []
        current_port = end_port + 1

if __name__ == "__main__":
    # 扫描本地3000-4000端口
    check_range_ports("127.0.0.1", 3000, 4000)

关键修复点

  • 移除异常中的sys.exit():单个线程的错误仅打印提示,不影响其他线程执行。
  • 添加文件写入锁:避免多线程同时写入导致内容丢失或乱码。
  • 修正批次端口计算逻辑:用min()确保最后一批次的端口范围正确,无遗漏。
  • 取消守护线程设置:保证线程能完成全部任务再结束。

内容的提问来源于stack exchange,提问作者bringand1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 00:10:42