Python:为什么线程目标被读作变量?

时间:2014-11-19 02:25:52

标签: python multithreading

import urllib.request
import shutil
import os
import threading
import time

def downloadSize():
    while True:
        statinfo = os.path.getsize('minecraft_server.1.8.jar')
        statinfo = statinfo/8
        print(statinfo + "K")
        time.sleep(1)

def downloadFile():
    with urllib.request.urlopen('https://s3.amazonaws.com/Minecraft.Download/versions/1.8/minecraft_server.1.8.jar') as response, open('minecraft_server.1.8.jar', 'wb') as out_file:
        shutil.copyfileobj(response, out_file)

def Main():
    downloadSize = threading.Thread(target=downloadSize, args=())
    downloadFile = threading.Thread(target=downloadFile, args=())
    downloadFile.start()
    time.sleep(1)
    downloadSize.start()

if __name__ == '__main__':
    Main()

当我运行此代码时,当我尝试启动downloadSize线程时,我一直收到错误,我只是想不出来?我使用的是Python 3.4.2。

Traceback (most recent call last):
  File "C:\Users\my_username\Desktop\test.py", line 26, in <module>
    Main()
  File "C:\Users\my_username\Desktop\test.py", line 19, in Main
    downloadSize = threading.Thread(target=downloadSize, args=())
UnboundLocalError: local variable 'downloadSize' referenced before assignment

2 个答案:

答案 0 :(得分:2)

问题在于您尝试对全局函数和局部变量使用相同的名称:

downloadSize = threading.Thread(target=downloadSize, args=())

这不仅会让人类读者感到困惑,而且还会让Python编译器感到困惑。无论何时在函数内部赋值变量,都会使该变量名称成为整个函数的局部变量。*因此,当它试图评估threading.Thread(target=downloadSize, args=())时,因为downloadSize是一个局部变量,还没有被分配,你得到UnboundLocalError

修复很简单:不要重复使用变量名来表示同一范围内的不同内容。称之为downloadSizeThread或其他任何内容。

(当然,下一行你也有同样的问题。)


*除非您使用globalnonlocal语句。但这只会导致不同的问题 - 第一次运行时,它会用全局线程对象替换全局函数,并且您再也无法访问该函数了。

答案 1 :(得分:2)

您对局部变量和全局函数使用相同的名称。更改其中一个以解决问题。

downloadSize = threading.Thread(target=downloadSize, args=())
^------ This matches this ----------------^
downloadFile = threading.Thread(target=downloadFile, args=())
^------ Same here ------------------------^