满眼喜欢990 2024-05-07 13:25 采纳率: 0%
浏览 2

python2.7多线程锁相关的问题,求解

本人大学生一枚,不是很懂python,为什么代码单独跑能行,封装成函数之后传值就有问题了,是多线程锁相关的问题吗?求解答

import socket, time, thread,os

socket.setdefaulttimeout(3)


def socket_port(ip, port):
    """
    输入IP和端口号,扫描判断端口是否开放
    """
    try:
        if port >= 65535:
            print u'端口扫描结束'
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = s.connect_ex((ip, port))
        if result == 0:
            lock.acquire()
            print ip, u':', port, u'端口开放'
            try:
                print port
                sqlAdd = 'insert into portsscan(port)VALUES ("%s;")' % port
                cursor.execute(sqlAdd)
                db.commit()
            except Exception, e:
                print'2', e
            lock.release()
        s.close()
    except:
        print u'端口扫描异常'


def ip_scan(ip):
    """
    输入IP,扫描IP的0-65534端口情况
    """
    try:
        print u'开始扫描 %s' % ip
        start_time = time.time()
        for i in range(0, 65534):
            thread.start_new_thread(socket_port, (ip, int(i)))
        print u'扫描端口完成,总共用时 :%.2f' % (time.time() - start_time)
        raw_input("Press Enter to Exit")
    except:
        print u'扫描ip出错'

import pymysql
def main(url):
    global db,cursor
    try:
        db=pymysql.connect('localhost','root','root','test')
        cursor=db.cursor()
        sqlDelete='delete from portsscan'
        cursor.execute(sqlDelete)
        db.commit()
    except Exception,e:
        print '1',e
    lock = thread.allocate_lock()
    ip_scan(url)
    db.close()
    return

target='192.168.242.189'
main(target)

#这下面能正常运行,而上面封装函数运行就不行
a='192.168.242.189'
global db,cursor
try:
    db=pymysql.connect('localhost','root','root','test')
    cursor=db.cursor()
    sqlDelete='delete from portsscan'
    cursor.execute(sqlDelete)
    db.commit()
except Exception,e:
    print '1',e
lock = thread.allocate_lock()
ip_scan(a)
db.close()
  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-07 13:25
    关注

    引自免费微信小程序:皆我百晓生

    在你的代码中,问题主要出现在全局变量管理和多线程同步上。为了解决这个问题,我们可以将数据库连接、游标和锁作为参数传递给函数,这样每个线程都可以独立管理它们,并且避免了全局变量导致的潜在竞争条件。

    下面是修改后的代码:

    import socket
    import time
    import threading
    import os
    import pymysql
    
    socket.setdefaulttimeout(3)
    
    def socket_port(db, cursor, lock, ip, port):
        """
        输入IP和端口号,扫描判断端口是否开放
        """
        try:
            if port >= 65535:
                print(u'端口扫描结束')
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = s.connect_ex((ip, port))
            if result == 0:
                lock.acquire()
                print(ip, u':', port, u'端口开放')
                try:
                    print(port)
                    sqlAdd = 'INSERT INTO portsscan(port) VALUES ("%s";)' % port
                    cursor.execute(sqlAdd)
                    db.commit()
                except Exception as e:
                    print('2', e)
                lock.release()
            s.close()
        except:
            print(u'端口扫描异常')
    
    
    def ip_scan(db, cursor, lock, ip):
        """
        输入IP,扫描IP的0-65534端口情况
        """
        try:
            print(u'开始扫描 %s' % ip)
            start_time = time.time()
            threads = []
            for i in range(0, 65534):
                t = threading.Thread(target=socket_port, args=(db, cursor, lock, ip, i))
                threads.append(t)
                t.start()
    
            for t in threads:
                t.join()
    
            print(u'扫描端口完成,总共用时 :%.2f' % (time.time() - start_time))
            input("Press Enter to Exit")
        except:
            print(u'扫描ip出错')
    
    def main(url):
        try:
            db = pymysql.connect('localhost', 'root', 'root', 'test')
            cursor = db.cursor()
            sqlDelete = 'DELETE FROM portsscan'
            cursor.execute(sqlDelete)
            db.commit()
        except Exception as e:
            print('1', e)
        lock = threading.Lock()
        ip_scan(db, cursor, lock, url)
        db.close()
    
    target = '192.168.242.189'
    main(target)
    

    这段代码做了以下改进:

    1. 将数据库连接、游标和锁作为参数传递给ip_scan()socket_port()函数。
    2. 使用threading.Thread替换thread.start_new_thread,这是Python 2.7中的推荐做法。
    3. ip_scan()中,创建一个列表存储所有线程并调用t.start()启动它们。然后遍历线程列表并调用t.join()等待所有线程完成。

    现在,这个版本应该可以正确地处理多线程并发访问数据库的情况。同时,它也避免了使用全局变量带来的潜在问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 5月7日

悬赏问题

  • ¥15 soildworks装配体的尺寸问题
  • ¥100 有偿寻云闪付SDK转URL技术
  • ¥30 基于信创PC发布的QT应用如何跨用户启动后输入中文
  • ¥20 非root手机,如何精准控制手机流量消耗的大小,如20M
  • ¥15 远程安装一下vasp
  • ¥15 自己做的代码上传图片时,报错
  • ¥15 Lingo线性规划模型怎么搭建
  • ¥15 关于#python#的问题,请各位专家解答!区间型正向化
  • ¥15 unity从3D升级到urp管线,打包ab包后,材质全部变紫色
  • ¥50 comsol温度场仿真无法模拟微米级激光光斑