2

我有一个锻炼,现在很好并且正在运行。本练习的算法是从 FTP 服务器下载文件 zip 并再次将其上传到 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

4 回答 4

4

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

以下是您可以进行的操作:

  1. 确定你的方法在做什么,每一个都应该有一个精确的目标
  2. 确定为此目的需要什么,并将其放入参数列表中
  3. 确定它应该返回什么并返回它
  4. 您的主要功能很好,并且是集中这些变量的理想场所

不使用全局变量并拥有一种功能/一种方法的最好的一点是,当出现问题时,测试/调试将非常容易。

例子:

你的download_files()requiresdownloadstemp_path,使它们成为参数,而不是全局变量

于 2012-07-04T07:42:33.347 回答
2

到目前为止,您有四个全局变量main。(temp_path, uploads, downloadsftp)。

首先,用 global 删除(注释)行,然后这 4 个变量将变成 local 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 filepathin zipping_files())。

于 2012-07-04T08:08:10.937 回答
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()

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

于 2012-07-04T08:48:25.260 回答
-1

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

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

于 2012-07-04T07:45:35.513 回答