使用Python 3.2.2进行多线程尝试:"AttributeError: 'str'对象没有属性'_initialized

0 投票
3 回答
3109 浏览
提问于 2025-04-17 05:49

我在使用以下Python 3.2.2代码时遇到了问题。这段代码是我用来测试另一个应用程序的反应时间的。我的想法是让另一个脚本(可以是任何类型的)传递给这个计时程序,并对环境进行一些修改。这个脚本应该在一个单独的线程中运行,这样我就可以从脚本开始时就开始计时,而不是等到结束时。接下来的代码则是用来计时应用程序对那个脚本的反应。我试着参考了threading模块的文档来创建这个代码,我相信我已经仔细阅读过,但我总是遇到以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python32\lib\threading.py", line 669, in start
    if not self._initialized:
AttributeError: 'str' object has no attribute '_initialized'

这是线程类的定义。

import threading, ...

class AsyncScript(threading.Thread):
    def __init__(self, s):
        self.script = s
    def run(self):
        print ("Beginning script...")
        try:
            os.system("cmd /k " + self.script)
        except:
            sys.exit("Error running script " + self.script)

这个类在脚本的其他地方被调用,方式是AsyncScript.start(options.script),其中options类包含传递给脚本的选项(使用argparse模块)。

你觉得我可能哪里做错了呢?


好的,更新一下。下面这个(简化版的)代码确实可以工作,老实说我也不太明白为什么——我看不出有什么不同。

import threading

class AsyncScript(threading.Thread):
    def __init__(self, s):
        threading.Thread.__init__(self)
        self.script = s
    def run(self):
        print("This would run script " + self.script)

AsyncScript("sample script path string").start()

输出结果是,恰如其分,

这将运行脚本示例脚本路径字符串

除了包含threading.Thread.__init__(self)这一行,我之前在早期版本的代码中加过这个,但没有成功,我现在真的不太确定这里有什么不同。我错过了什么呢?

3 个回答

0

你的 self.script 没有被初始化,但你有 self.s - 试着用它吧。

1

在脚本的其他地方,这段代码是通过 AsyncScript.start(options.script) 来调用的。

这个调用是错误的。你把 threading.Thread 的无参数(不算 self)的 start 方法当成了你的脚本字符串来用,而不是先创建一个 AsyncScript 类的实例(把字符串传给 __init__),然后再调用这个实例的线程对象的 .start() 方法。显然,一个字符串不是一个线程,所以当你把字符串当作 self 传给线程代码时,它会出错。正确的写法应该是 AsyncScript(options.script).start()

0

如果你已经在一个单独的进程中运行脚本,那就不需要使用线程。可以用 subprocess 来代替 os.system()

你不需要去继承 Thread 类来创建一个线程:

Thread(target=func, args=func_args).start()

我不太明白这里有什么不同。我错过了什么吗?

这里有两个不同之处:

  1. AsyncScript.start(options.script)AsyncScript(options.script).start()

    AsyncScript 是一个类对象,而 AsyncScript(options.script) 是这个类的一个实例。

    AsyncScript.start(options.script) 调用的是一个未绑定的 .start 方法。它期望第一个参数是一个 AsyncScript 实例,而不是一个字符串 options.script。正确的调用方法是 obj.method()。在你的例子中,obj = AsyncScript(options.script)

  2. AsyncScript.__init__() 方法中有 threading.Thread.__init__(self) 的存在。

    如果你不调用 threading.Thread.__init__(self),那么线程的属性,比如 _initialized 就不会被创建或定义。

撰写回答