误导性的全局变量

时间:2012-07-04 07:36:49

标签: python ftp download ftputil

我有一个练习,它现在很好并且正在运行。本练习的算法是从FTP服务器下载文件,然后再次将其上传到FTP服务器的上传文件夹中。顺便说一句,这是我的代码:

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()

好的,命名惯例留给我。但我想问一个例子,我怎么能在不使用所有全局变量的情况下重新编码呢?谢谢你的帮助!

4 个答案:

答案 0 :(得分:4)

你应该明确地为你的方法提供参数。

以下是您可以继续的方式:

  1. 确定您的方法正在做什么,每个方法应该只有一个确切的目标
  2. 确定为此目的所需的内容,并将其放入参数列表
  3. 确定返回的内容并将其归还
  4. 您的主要功能很好,是集中这些变量的理想场所
  5. 不使用全局变量并拥有一个函数/一个方法的最佳点之一是,当出现问题时,它将非常容易进行测试/调试。

    示例:

    您的download_files()需要downloadstemp_path,让他们成为参数,而不是全局

答案 1 :(得分: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 filepath中的zipping_files())。

答案 2 :(得分: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()

任何建议都将被考虑!再次感谢!

答案 3 :(得分:-1)

Python并不真正支持全局变量 - 它们通常是一个坏主意。要么将数据作为参数传递,要么将函数包装在类中,并将参数用作类成员。

(从技术上讲,python有全局关键字,但你必须在每个全局变量的每个函数中使用它。它应该是丑陋的。不要使用它。)