我有一个非常简单的 Python 脚本——flickr.py——它可以将文件上传到 Flickr。它看起来像这样:

#!/usr/bin/python
import sys
import os.path
import flickr_api
KEY = '<key>'
SECRET = '<secret>'
filename = sys.argv[1]
basename = os.path.basename(filename)
flickr_api.set_keys(api_key=KEY, api_secret=SECRET)
flickr_api.set_auth_handler('/home/pi/.flickr/token')
flickr_api.upload(photo_file=filename, title=basename)

效果很好。我输入 flickr photo.jpg,它就在我的 Flickr 页面上。

但是,我想限制上传速度,以便我可以在后台运行它而不会严重影响其他 Internet 流量。所以我跑...
trickle -s -u 10 flickr photo.jpg
...而且,可悲的是,似乎没有像我希望的那样将上传速度限制到 10kbps。我已经在另一个窗口中打开 NetHogs 进行了测试。最高可达 80kbps,就像我在没有 trickle 的情况下运行它一样。

我尝试了各种方法——以 super 用户身份运行它,在命令前面加上我的 Python 解释器 ( trickle -s -u 10 /usr/bin/python flickr photo.jpg ) 的完整路径。似乎没有任何效果。

我已经用这个盒子上的其他程序测试了 trickle —— wgetscp —— 它完全按预期工作。我错过了什么?

可能相关的注释:这是在 Raspberry Pi 上。

更新: 我使用的 Flickr API 模块是这个...

https://github.com/alexis-mignon/python-flickr-api

......但我只是用这个重写了我的例子......

http://stuvel.eu/flickrapi

......结果相同。

最佳答案

TL; 博士
OP 问题无法在相同的硬件上重现,因此我认为这是对单位( 10 KB/s == 80 kbps )的误读。一个类似但不完全相同的问题引发了对该问题的赏金,因此我为此提供了一些诊断技术。我已将回复分成几部分:

  • 原始问题
  • 诊断步骤建议
  • 使用 awscli
  • 可能是什么问题的假设

    1.原始问题(非)再现
    我使用 Raspbian OS(无 GUI)设置了 Raspberry Pi,其库与 OP 完全相同(全部使用 sudo 完成以提高速度......)
    sudo pip install flickr_api
    sudo apt-get install nethogs
    sudo apt-get trickle
    
    然后,您必须注册一个 Flickr 帐户,创建一个(非商业)应用程序并设置 API key 等 - app creation here 和 api key 获取 here 的说明,或者通过 Python 包装器 here
    我找到了一个 1.9MB 的图像,将其命名为 test.jpg 并尝试了以下操作:
  • /usr/bin/python flickr.py test.jpg
  • trickle -s -u 10 /usr/bin/python flickr.py photo.jpg

  • 结果
  • 上传时间为 ~ 3 secs 的图片,其中 nethogs 显示了峰值上传速度 ~ 400KB/s
  • 图片上传时间超过一分钟,nethogs 显示上传速率在 13 KB/s 处达到峰值(简要),然后稳定在 10.081 处。

  • 一切正常
    因此,我认为 OP 问题就这么简单:trickle 中的上传限制设置为每秒 千字节 ( kB/s ),我认为 OP 可能正在读取每秒千 的速度( kbps )。因此系数为 8。

    2. 然而...类似问题的诊断
    @James_pic 在这个问题上发布了悬赏,结果证明他的场景与 OP 不同。特别是,他在使用 aws-cli 上传到 Amazon Web 服务时观察到没有限制
    既然如此,我将发布一些进一步的诊断方法。 paper describing how trickle works is here and 描述了一些 trickle 不起作用的场景:
  • 当用户不主动在滴流下运行时
  • 其次,由于影响较小,Trickle 无法处理静态链接的二进制文件。

  • 2 在这里可能是相关的,所以我将概述一种方法,您可能会开始使用 strace 进行诊断。此站点上还有另一个问题,涉及 strace usage in general 和查找使用中的共享库的特定用法 here
    由于我没有 aws-cli 的可重现示例,我将展示我在 flickr_api 案例中验证操作时所做的工作。
    从手册页,strace
  • strace /usr/bin/python flickr.py test.jpg 2>&1 | grep open > strace.out
  • strace trickle -s -u 10 /usr/bin/python flickr.py test.jpg | grep open > strace_with_trickle.out

  • 最后,我运行了这两个文件的差异:
    diff strace_with_trickle.out strace.out
    
    不出所料,带有 trickle 的版本输出了更多行——特别是这些:
    < open("/lib/arm-linux-gnueabihf/libbsd.so.0", O_RDONLY) = 3
    < open("/lib/arm-linux-gnueabihf/libc.so.6", O_RDONLY) = 3
    < open("/lib/arm-linux-gnueabihf/libgcc_s.so.1", O_RDONLY) = 3
    < open("/usr/lib/trickle/trickle-overload.so", O_RDONLY) = 3
    < open("/etc/ld.so.preload", O_RDONLY)    = 3
    < open("/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so", O_RDONLY) = 3
    < open("/etc/ld.so.cache", O_RDONLY)      = 3
    
    这些是在进程运行时覆盖 trickle-overload.so 插入的行。特别是,我们可以观察到标准套接字库正在使用中并在此处动态加载 - 即 libc.so.6libbsd.so.0 ,这让我们相信 trickle 应该可以工作。
    这种技术非常通用 - 使用一个工作案例和一个非工作案例,然后 diff 输出应该会让你走得更远。

    3. 最后... awscli 假设
    我怀疑 awscli 可能会在上传过程中产生新进程。如果是这种情况,我认为带有 trickle 选项的 -s 不会限制这些子进程。您可以在守护程序模式下使用它 - 这可能会更好 - 您可以通过键入 man trickled 来查看如何执行此操作
    本质上 - 您首先启动守护进程,例如
    trickled -u 10
    
    然后“订阅”它的进程,例如
    trickle /usr/bin/python flickr.py test.jpg
    
    警告 我没有可重现的 awscli 问题的测试用例,所以这是推测。

    关于python - Trickle 无法调整我的 Python 脚本的上传带宽,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22851332/

    10-13 06:32