歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

使用Python多線程犯的錯誤總結

在使用Python多線程的時候,在使用多線程編程的時候,由於對於變量作用域和多線程不是很熟悉,導致在使用多線程的時候,犯了低級的錯誤。

 第一個錯誤:

在多線程中使用全局變量,導致多個線程修改全局變量。執行信息錯亂,開始是幾個個進程,後面就變成一個了。後來經過重新學習多線程,才把原來的錯誤修改過來。

 腳本功能,多線程向設備上傳和下載文件,測試ftp功能和性能。錯誤原因是把ftp變量設置為了全局變量,導致出現怪異的現象,開始有幾個線程在跑,然後幾個進程退出,最後變為一個,還出現了ftp密碼錯誤的提示。當時調試了好久,後來使用pycharm工具,觀察到了問題的原因。

代碼如下:

紅色的代碼為錯誤的版本,最初的時候,ftp變量在外面,作為全局變量使用。綠色的代碼為修改正確的版本。

#! /usr/bin/env python
#coding=utf-8

from ftplib import FTP
from datetime import datetime
import sys
import os
import threading

FTP_Port='21'
Telnet_Port='23'
buffsize=1024
#ftp=FTP()
class ftp_test(threading.Thread):
    upload_dir="../upload/"
    download_dir="../download"
    IP =''
    Username=''
    Password=''
       
    def __init__(self,env_para):
        threading.Thread.__init__(self)

        self.IP=env_para['IP_Addr']
        self.Password= env_para['Password']
        self.Username= env_para['admin']
        self.upload_dir= env_para['upload_dir']
        self.download_dir= env_para['download_dir']

    def ftp_upload(self,tfile):
        ftp=FTP()
        ftp.connect(self.IP, FTP_Port,timeout=10)
        ftp.login(self.Username,self.Password)
        #print ftp.getwelcome()
        ftp.cwd(ramdisk)
        #print ftp.dir()

        file_handler=open(self.upload_dir + tfile,'rb')
        ftp.storbinary('STOR '+ tfile ,file_handler,buffsize)
        #ftp.dir()

        file_handler.close()
        ftp.quit()
        print tfile,' Upload OK'

    def ftp_download(self,t_file):
        ftp=FTP()
        ftp.connect(self.IP, FTP_Port,timeout=10)
        #ftp.set_debuglevel(2)
        ftp.login(self.Username,self.Password)

        filename = t_file +'_download'
        file_write=open( self.download_dir + filename,'wb').write
        ftp.retrbinary('RETR '+ filename, file_write, buffsize)
        ftp.delete(filename)
        ftp.quit()
        print t_file,' FTP download OK'

    def run(self):
        file_list=os.listdir(self.upload_dir)
        for each_file in file_list:
            try:
                self.ftp_upload(each_file)
            except Exception ,e:
                print each_file ,' FTP Upload fail'
                print e

            try:
                self.ftp_download(each_file)
            except Exception ,e:
                print each_file ,' FTP download fail'
                print e

這樣在函數中定義,縮小了ftp變量的作用域,終於完成了ftp並行的上傳和下載。

定位過程:

在使用pycharm調試時,觀察ftp變量的變化,發現只有一個ftp變量,所有的進程都使用的是這一個變量,ftp變量記錄的ftp狀態不斷在變化,出現了各種奇怪的現象。

在縮小了ftp變量的作用域後,重新調試,觀察到ftp變量在每個進行中的地址都不一樣,每個ftp的變化不受其他進程影響。

第二個錯誤:

因為在網絡上學習分享的多線程文章,受  http://www.linuxidc.com/Linux/2015-06/119279.htm 這個分享的影響,在線程啟動後,直接寫了t.join(),不是把所有的進程都加了join。

導致執行慢的進程被主線程直接終止,出現了多次ftp沒有執行完成,線程就退出。

正確的寫法是:

for t in threads:

  t.join()

這個分析當時把我害苦了,調試了老半天才發現這個錯誤。

總結心得:

對於學習還是要看書籍系統的學習。

另外,學會使用工具調試,觀察變量的變化,深入理解程序運行,方便定位問題。

Copyright © Linux教程網 All Rights Reserved