2012-07-04 58 views
2

我有一個練習,它現在很好,並且正在運行。本練習的算法是從FTP服務器下載文件並將其再次上載到FTP服務器的上傳文件夾中。 BTW這是我的代碼:具有誤導性的全球變數

import os 
import zipfile 
import ConfigParser 
import ftputil 
import shutil 
import tempfile 
import time 


def download_files(): 
    # Alvin: Think of a better variable name 
    file_list = ftp.listdir(downloads) 
    for filename in file_list: 
     # Alvin should be ftp.path.join 
     source = os.path.join(downloads, filename) 
     target = os.path.join(temp_path, filename) 
     ftp.download(source, target) 

def zipping_files(): 
    dirlist = os.listdir(temp_path) 
    global filepath 
    filepath = os.path.join(temp_path, 'part2b.zip') 
    # Alvin: find better name for zip_name 
    global zip_name 
    zip_name = zipfile.ZipFile(filepath, 'w') 
    # Alvin: try not to use built-in names as variable names 
    for list in dirlist: 
     # Alvin: file_path, absolute_path 
     get_file = os.path.join(temp_path, list) 
     zip_name.write(get_file, 'part2b\\' + list) 

def upload_files(): 
    ftp.upload(filepath, uploads + '/part2b.zip') 

def main(): 
    # Alvin: Do not use globals. 
    # Alvin: remove useless and above all misleading comments 

    global temp_path 
    temp_path = tempfile.mkdtemp() 


    config = ConfigParser.ConfigParser() 
    config.readfp(open('config.ini')) 
    server = config.get('main', 'Server') 
    username = config.get('main', 'Username') 
    password = config.get('main', 'Password') 

    global uploads 
    uploads = config.get('main', 'Upload folder') 

    global downloads 
    downloads = config.get('main', 'Download folder') 

    #connect to ftp 
    global ftp 
    # Alvin: open ftp connection when you only need it. 
    ftp = ftputil.FTPHost(server, username, password) 

    try: 
     download_files() 
     zipping_files() 
     upload_files() 

    finally: 
     ftp.close() 
     zip_name.close() 
     shutil.rmtree(temp_path, 'true') 

    print "Successfully transferred files." 
    print "" 
    print "This will close in 5 seconds. . . . ." 
    time.sleep(5) 

if __name__ == '__main__': 
    main() 

好吧,命名約定留給我。但是我想問一個如何重新編碼而不使用全部全局變量的例子?謝謝你的幫助!

+0

將這些變量作爲參數傳遞。 – georg

+0

我會嘗試一下這個建議,其實我有這個想法,但我不確定我是否會首先聲明變量?或者它可以在我的main()函數中聲明,對不起,在Python中我是新的。不管怎麼說,還是要謝謝你! – neo

+0

在python中,你不必在賦值之前聲明變量。 –

回答

4

你應該明確地給你的方法提供參數。

這裏是你如何進行:

  1. 識別你的方法做,每個人只能有一個精確的目標
  2. 確定什麼是需要爲此,並把它在參數列表
  3. 確定它應返回並返回
  4. 你的主要功能是好的,是爲了集中這些變量的理想場所

不使用全局變量和有一個函數/一個方法的最好的一點是,當出現錯誤時,它將很容易測試/調試。

例子:

download_files()需要downloadstemp_path,使他們的論點,而不是全局

+0

如果將'try:'/'finally:'分開,並且像拉鍊這樣的東西的關閉發生在打開的位置,那麼該方法就有效。 – glglgl

+0

好吧,是的,顯然'zipping_files()'打開'zip_name',它應該負責關閉它 –

+0

好吧,我會嘗試在我的函數中使用參數。每當我完成時,我會更新你們。感謝你的幫助! – neo

-1

的Python真的不支持全局變量 - 它們通常是一個壞主意。可以將數據作爲參數傳遞,也可以將您的函數包裝到類中,然後將這些參數用作類成員。

(從技術上說,蟒蛇有全球關鍵字,但你必須在每一個全局變量的每個功能來使用它。這是醜陋的,因爲它應該是,不要使用它。)

+0

這個答案既不正確也不好建議。您*不必*必須使用關鍵字才能使用全局變量,只能更改它。是的,它具有全局(即模塊)變量。 – PierreBdR

2

你有截至目前,您的main中有四個全局變量。 (temp_path, uploads, downloadsftp)。

首先,刪除(註釋)全局行,然後這4個變量將本地變爲main。但是這會讓他們無法進入其他功能。所以,你需要將它們傳遞給函數。

爲此,您可以將這些變量作爲參數添加到需要它們的函數中。因此,舉例來說,你try塊將改變..

try: 
    download_files(downloads, temp_path) 
    zipping_files(temp_path) 
    upload_files(ftp) 

現在,以匹配另外的參數,你必須轉變職能了。 的這是從try塊被稱爲函數的簽名是:

def download_files(downloads, temp_path): 

def zipping_files(temp_path): 

def upload_files(ftp): 

同樣,你可以刪除你在其他功能上也有全局變量(如global filepathzipping_files())。

0

謝謝各位的幫助!你所有的答案都非常有幫助!這是我的最終和運行代碼:

import os 
import zipfile 
import ConfigParser 
import ftputil 
import shutil 
import tempfile 
import time 


def download_files(downloads, temp_path, server, username, password): 
    ftp = ftputil.FTPHost(server, username, password) 
    file_list = ftp.listdir(downloads) 
    for filename in file_list: 
     source = os.path.join(downloads, filename) 
     target = os.path.join(temp_path, filename) 
     ftp.download(source, target) 
    ftp.close() 

def zipping_files(temp_path): 
    file_list = os.listdir(temp_path) 
    filepath = os.path.join(temp_path, 'part2b.zip') 
    zip_file = zipfile.ZipFile(filepath, 'w') 
    for filename in file_list: 
     file_path = os.path.join(temp_path, filename) 
     zip_file.write(file_path, 'part2b\\' + filename) 
    zip_file.close() 

def upload_files(uploads, temp_path, server, username, password): 
    ftp = ftputil.FTPHost(server, username, password) 
    filepath = os.path.join(temp_path, 'part2b.zip') 
    ftp.upload(filepath, uploads + '/part2b.zip') 
    ftp.close() 

def main(): 

    temp_path = tempfile.mkdtemp() 

    config = ConfigParser.ConfigParser() 
    config.readfp(open('config.ini')) 
    server = config.get('main', 'Server') 
    username = config.get('main', 'Username') 
    password = config.get('main', 'Password') 
    uploads = config.get('main', 'Upload folder') 
    downloads = config.get('main', 'Download folder') 

    try: 
     download_files(downloads, temp_path, server, username, password) 
     zipping_files(temp_path) 
     upload_files(uploads, temp_path, server, username, password) 

    finally:  
     shutil.rmtree(temp_path, 'true') 

    print "Successfully transferred files." 
    print "" 
    print "This will close in 5 seconds. . . . ." 
    time.sleep(5) 

if __name__ == '__main__': 
    main() 

任何建議都將考慮!再次感謝!