【问题标题】:Upload using python script takes very long on one laptop as compared to another与另一台笔记本电脑相比,使用 python 脚本上传在一台笔记本电脑上需要很长时间
【发布时间】:2012-09-06 12:46:04
【问题描述】:

我有一个 python 2.7 代码,它使用 STORBINARY 函数将文件上传到 ftp 服务器,并使用 RETRBINARY 函数从该服务器下载。

但是,与戴尔笔记本电脑相比,不同品牌的三台笔记本电脑的上传需要很长时间。奇怪的是,当我手动上传任何文件时,所有系统都需要相同的时间。

手动上传速率和使用 python 脚本的上传速率在戴尔笔记本电脑上是相同的。但是,在所有其他品牌的笔记本电脑上(我尝试过使用 IBM、Toshiba、Fujitsu-Siemens),python 脚本的上传速率都比手动尝试的低。此外,在所有这些其他笔记本电脑上,使用 python 脚本的上传速率是相同的(1Mbit/s),而手动上传速率大约是 1Mbit/s。 8 兆比特/秒。

我已尝试更改上传文件的大小,但无济于事。 TCP Optimizer 提高了所有系统的下载速率,但对上传速率没有影响。在所有系统上使用此脚本的下载速度都很好,与手动下载速度相同。

我检查了服务器,它有超过 90% 的可用空间。所有笔记本电脑的网络连接都是相同的,我尝试一次只用一台笔记本电脑上传。所有笔记本电脑都具有几乎相同的系统配置、相同的操作系统和大致相同的可用驱动器空间。如果戴尔笔记本电脑在处理能力和 RAM 方面比其他 2 台笔记本电脑少一点,但我认为这没有影响,因为我已经检查了很多次,看看这些上传期间的 CPU 使用率和网络使用率有多少下载,我确信没有其他病毒或程序占用了我的带宽。


即使使用“storbinary”命令,当我将块大小指定为 57344(56 kB)时,上传速率从原来的 1 到 1.5 Kbit/s 提高到大约 5 Kbit/s...这是什么原因?以及如何找出我的手动上传客户端(我使用 filezilla)使用的块大小,或者更好的是上传的最佳块大小? @guidot


完整代码:

def upnew(counter=0):

    f=open("c:/10", "w")

    f.write(os.urandom(10*1024*1024))
    f.close()

    print "Logging in..."

    ftpserver='xxxxxxx'

    ftpuser='xxxxxxx'

    ftppw='xxxxxxxxx'

    ftp = FTP(ftpserver)    
    ftp.login(ftpuser, ftppw)  

    t = open("c:/10", "rb")                       
    upstart = time.clock() 

    ftp.storbinary('STOR 10', t)

    upende = time.clock()-upstart

    print ((10*8)/upende)

    print "press Return to disconnect"
    raw_input()

    ftp.quit()
    print "FTP Verbindung abgebaut"


upnew(1)

【问题讨论】:

  • 笔记本电脑都在运行windows?可以分享一下上传的代码吗?
  • 您是否隔离了任何正在进行的处理?无需任何数据处理或其他处理的简单“上传通用文本文件”功能将帮助您找出问题的根源。
  • 对于 S/O 来说有点离题,因为它并不是一个真正与编程相关的问题(除了 Python 恰好用于 FTP,它与系统/网络/设置更相关) - 可能是超级用户/管理员所有血淋淋的系统细节更有可能获得有用的答案。
  • 假设您的 ftp 参数是 FTP 模块:尝试找出手动传输方法使用的块大小,并将其作为第三个参数传递给 storbinary,以确保您以相同的方式进行传输。
  • 您可以观察wireshark 发生的情况——数据包时间戳可能会提供有关延迟位置的线索。听起来您已经做了所有正确的事情来缩小问题范围 - 祝您好运。

标签: python upload ftp


【解决方案1】:

Python 主要用于脚本和流程自动化,在技术上不被认为是一种快速变化的语言(尽管比大多数其他脚本语言更快)。 Filezilla 使用 C/C++ 编码,在性能上远远优于 Python。话虽如此,这不是一个公平的比较,我们应该在尝试识别可能导致一般性能问题的逻辑问题时考虑它。

storbinary 基本上充当 ntransfercmd 的包装器,调用 ntransfercmd 而不需要我们定义自己的缓冲区(这就是我之前推荐的原因)。

此外,在再次分析您的代码 snip-it 之后,我注意到您通过 print 语句调用 storbinary...这是错误的吗?

此时,我们将需要此示例中使用的所有相关代码来识别可能影响性能的任何逻辑问题,请在您之前的 snip-it 的基础上为我们提供更多信息。

这里要考虑的另一个因素是您进行测试的一般系统环境......考虑您执行所述测试的每个系统的位置,它们与 FTP 服务器的距离,此外,差异在对与基于 TCP/IP 的连接(如 ftp)相关的性能问题进行故障排除时,ISP 或 DNS 服务器可能会发挥主要作用。

【讨论】:

  • 如果您已经尝试了所有这些,但您仍然对应用程序的响应能力不满意,那么下一步就是使用套接字来中断进程(使用 ntransfercmd 或 transfercmd 函数) ...理论上,如果您使用套接字连接到 ftp 服务器,您可以同时传输多个块。但是,这是一个我没有资格处理的高级主题。如果你打算走这条路,我建议你开始一个新的线程/问题。
  • 很抱歉回复晚了,感谢您一直以来的帮助 Meikel...打印语句没有区别,有或没有结果都一样... C 之间的性能差异如果我测试的所有系统上的结果都相同,那么 python 可能是一个问题......所有系统都在相同的环境中进行了测试,在完全相同的距离和与互联网的相同连接......但是在戴尔笔记本电脑上,此 python 代码的上传速率与 Filezilla 客户端手动上传相同,而在所有其他系统上,这些上传速率下降
  • 我已经分别测试了代码的各个部分,我确信问题是因为这个STORBINARY而出现的。其中一台笔记本电脑具有与戴尔笔记本电脑几乎相同的配置和设置,相同的 RAM、可用内存、缓存和操作系统。戴尔笔记本电脑有 Broadcom NetXtreme 57xx 千兆控制器,而另一个系统有 Boradcom NetXtreme 千兆控制器,但我怀疑这对上传 10 MByte 文件有多大影响。两者的手动上传速度也相同。问题在于使用 STORBINARY 上传。
  • 我将尝试使用“ntransfercmd”并让您知道结果。同时,您能否让我知道 ISP 中的哪种差异会导致 Python 代码的上传性能问题..(因为我很确定这里的问题是代码而不是计算机的性能能力)
  • 所以..我也检查了 ntransfercmd 函数。与 STORBINARY 完全相同的上传速率。看来,对于“storbinary”和“ntransfercmd”,在更改块大小时上传速率会有所不同。 54 Mbyte 和 84 Mbyte 之间的块大小提供最佳上传速率(仍然比手动上传小一点)
【解决方案2】:

我可能错了,但问题似乎在于您调用和使用 ftp.storbinary() 的方式

我会尝试改用 ftp.ntransfercmd() 并在传输过程中使用缓冲区来分解传输。这为您提供了额外的好处,即能够跟踪 ftp 传输的进度,并且理论上允许您根据需要暂停和重新启动该过程。

尚未测试此脚本的性能,但您可以尝试执行以下操作:

    def ftpUploader():
        BLOCKSIZE = 57344 # size 56 kB

        ftp = ftplib.FTP()
        ftp.connect(host)
        ftp.login(login, passwd)
        ftp.voidcmd("TYPE I")
        f = open(zipname, 'rb')
        datasock, esize = ftp.ntransfercmd(
            'STOR %s' % os.path.basename(zipname))
        size = os.stat(zipname)[6]
        bytes_so_far = 0
        print 'started'
        while 1:
            buf = f.read(BLOCKSIZE)
            if not buf:
                break
            datasock.sendall(buf)
            bytes_so_far += len(buf)
            print "\rSent %d of %d bytes %.1f%%\r" % (
                  bytes_so_far, size, 100 * bytes_so_far / size)
            sys.stdout.flush()

        datasock.close()
        f.close()
        ftp.voidresp()
        ftp.quit()
        print 'Complete...'

【讨论】:

  • 即使使用 'storbinary' 命令,当我将块大小指定为 57344(56 kB) 时,上传速率从原来的 1 提高到 5 Kbit/s 到 1.5 Kbit/s...这是什么原因?以及如何找出我的手动上传客户端(我使用 filezilla)使用的块大小,或者更好的是上传的最佳块大小? @guidot
【解决方案3】:

请提供您的代码的工作示例...无法看到您如何实现 ftp 功能,不可能提供有用的反馈,但通常您可能会从使用线程或套接字中受益。

【讨论】:

猜你喜欢
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 2022-07-27
  • 1970-01-01
  • 2022-11-04
  • 2015-01-14
  • 2013-02-07
  • 1970-01-01
相关资源
最近更新 更多