我在从另一个Python脚本文件更新List L []的项目时遇到问题。 下面是我现在拥有的两个简单文件,任何帮助/建议/建议都将受到高度赞赏。
script1.py
import time, threading
L=[]
def first():
if len(L)!=0:
x = L.pop()
print 'The element', x, 'left the list L'
else:
print 'L is empty now ...'
threading.Timer(10, first).start()
first()
script2.py
from __main__ import *
import time
import script1
c = 1
def pass_arg():
global c
c+=1
L.append(c)
print 'will pass value to the list L of script1.py'
threading.Timer(10, pass_arg).start()
pass_arg()
我面临的问题是sript2无法访问script1的已定义列表L.此外,script2开始遵循script1的所有运行函数!?
非常感谢,
根据建议编辑上一代码后,现在我有以下脚本:
script1.py
from __main__ import *
import time, threading
class ListHolder:
def __init__(self):
self.L = []
def first(self):
if len(self.L)!=0:
x = self.L .pop()
print 'The element', x ,'left the list L'
else:
print 'L is empty now ...'
threading.Timer(10, self.first).start()
R = ListHolder()
R.first()
script2.py
from __main__ import *
import time, threading
from script1 import ListHolder
c = 1
X = ListHolder()
def pass_arg():
global c
c+=1
X.L.append(c)
print X.L
print 'will pass value to the list L of script1.py'
threading.Timer(10, pass_arg).start()
pass_arg()
现在的主要问题是script2.py新添加的项目没有传递给script1.py,因此script1.py中的List始终为空,并且更改未反映在script1列表中。有什么建议?
答案 0 :(得分:3)
Python没有真正的全局变量,或者至少它们不像你使用它们那样工作。对于它有什么价值,Stack Overflow上有很多其他答案,例如Using global variables in a function other than the one that created them,它们的答案详细说明了如何绕过默认行为,但它有点hacky而不是真的在大多数情况下Python希望你做什么。
你想要做的是在这里使用一堂课。
class ListHolder:
self.L=[]
然后你就可以访问ListHolder.L而不会有任何麻烦。从长远来看,你不想使用全局变量,所以python鼓励你在这里做正确的事。
如果您认为自己拥有自包含的代码,并且该代码应该包含在自己的文件中,那么类或模块通常是Python中的正确选择。
更新以响应OP的更新: 首先,让我们逐行浏览您的脚本并做一些评论。
我们将从script2.py
开始from __main__ import * #Don't need this.
import time, threading #We don't need threads to do this.
from script1 import ListHolder #This EXECUTES code in script1.py
c = 1 #fine
X = ListHolder() #Good
def pass_arg():
global c #not necessary
c+=1 #fine
X.L.append(c) #fine
print X.L #fine
print 'will pass value to the list L of script1.py' #You already did that.
threading.Timer(10, pass_arg).start() #You don't need this.
#furthermore it will execute forever and
#die when it blows the stack.
pass_arg() #this is fine
这是Script2.py
from __main__ import * #this is not needed.
import time, threading #We aren't using threads. Why import threads?
class ListHolder:
def __init__(self):
self.L = [] #This should be ok, but we could have also have initialized this
#in class scope rather than init.
def first(self):
if len(self.L)!=0:
x = self.L .pop()
print 'The element', x ,'left the list L'
else:
print 'L is empty now ...'
threading.Timer(10, self.first).start() #This will execute forever.
R = ListHolder() #as these are in "file" scope
R.first() #they will execute when imported!
因此,让我们将其简化为更好的格式。
Script2b.py
from script1b import ListHolder
c = 1 #fine
X = ListHolder() #Good
def pass_arg(z): #Functions need arguments.
z+=1 #we should use function scope vars
#instead of mutating global scope.
X.L.append(c) #fine
print X.L #fine
return z #return locally mutated data
#instead of mutating global scope.
for x in range(1,10):
c = pass_arg(c) #this is fine
X.popMe()
script1b.py
class ListHolder:
def __init__(self):
self.L = [] #This should be ok, but we could have also have initialized this
#in class scope rather than init.
def popMe(self):
if len(self.L)!=0:
x = self.L .pop()
print 'The element', x ,'left the list L'
else:
print 'L is empty now ...'
既然你一直在尝试使用线程,我怀疑你正在尝试做一些与帖子说的有点不同的事情。我怀疑您的印象是您可以同时运行两个脚本 并使用线程界面在两个脚本之间进行通信。
不是这样!
要考虑几点:
1)您已经编写了一个带线程的脚本。
这不会导致并行执行,并且脚本将不会彼此独立地运行。您只是在脚本之间产生控制权。线程最适合异步操作 - 它不会导致并行执行或独立状态。考虑事件处理程序和回调等情况。
2)Python本身并不支持Parallelism Pe Se:
Python并不是并行编程的绝佳选择。您可以使用"流程"开始独立进程的类,然后在外部管理它们。然而,"过程"不了解这些过程是Python程序,你不能直接影响他们的变量。执行此操作的方法是运行小进程,并返回中央进程的值以进行推理。想想OpenGL着色器。
3)您没有正确管理线程之间的状态。
无法保证线程的执行时间。您的原始脚本有时可能有效,而其他时间则无法运行。您需要使用锁/互斥锁来防止数据争用。如果您真的打算使用线程,则需要仔细考虑如何保护数据与数据集。如果你需要帮助,你应该开始一个关注它的新问题。
4)你几乎肯定不需要线程。
根据您的编程知识水平,我猜您实际上并不需要线程来完成您的任务。程序员大多数时候应该避免使用显式线程,直到绝对不可避免。