简体   繁体   English

脚本中的Python变量范围问题

[英]Python variable scope issue in script

I'm coming across some weirdness with a variable not being accessible in other functions after being set. 设置后,我遇到了一些奇怪的问题,该变量无法在其他函数中访问。 This is a Celery task file named html.py 这是一个名为html.py的Celery任务文件

base_path = ''

@app.task(bind=True)
def status(self):
    """
    returns the count of files downloaded and the timestamp of the most recently downloaded file
    """

    num_count = 0
    latest_timestamp = ''
    for root, _, filenames in os.walk(base_path):
        for filename in filenames:
            file_path = root + '/' + filename
            file_timestamp = datetime.fromtimestamp(os.path.getctime(file_path))
            if latest_timestamp == '' or file_timestamp > latest_timestamp:
                latest_timestamp = file_timestamp
            num_count += 1

@app.task(bind = True)
def download(self, url='', cl_id=-1):
    if len(url) == 0 or cl_id < 0:
        return None

    base_path = settings.WGET_PATH + str(cl_id)

    log_paths = {
        'output' : wget_base_path + '/out.log',
        'rejected' : wget_base_path + '/rejected.log'
    }

    create_files(log_paths)
    wget_cmd = 'wget -prc --convert-links --html-extension --wait=3 --random-wait --no-parent ' \
                   '--directory-prefix={0} -o {1} --rejected-log={2} {3}'.\
        format(wget_base_path, log_paths['output'], log_paths['rejected'], url)

    subprocess.Popen(wget_cmd, shell = True)

When I call this via 当我通过

from ingest.task import html
web_url = 'https://www.gnu.org/software/wget/manual/html_node/index.html'
ingest = html.download.delay(web_url, 54321)

the wget process kicks off as expected. wget进程按预期启动。 However, the base_path parameter at the top of the file never gets set, so when I call status via 然而, base_path在文件的顶部参数永远不会被设置,所以当我打电话status通过

status = html.status.delay()

the base_path variable is an empty string, despite status being called after download . 尽管在download后调用了statusbase_path变量还是一个空字符串。 Is this because these tasks are in a script vs a class? 这是因为这些任务在脚本中还是在类中?

Because in function download at this line 因为在功能上download此行

base_path = settings.WGET_PATH + str(cl_id)

you just creates a local variable with name base_path . 您只需创建一个名称为base_path的局部变量。 To avoid it you should declare base_path in function as global . 为了避免这种情况,您应该在function中将base_path声明为global For example: 例如:

@app.task(bind = True)
def download(self, url='', cl_id=-1):
    if len(url) == 0 or cl_id < 0:
        return None

    global base_path
    base_path = settings.WGET_PATH + str(cl_id)
...

From Python docs : 来自Python 文档

At any time during execution, there are at least three nested scopes whose namespaces are directly accessible: 在执行过程中的任何时候,至少有三个嵌套作用域可以直接访问其名称空间:

  • the innermost scope, which is searched first, contains the local names 最里面的作用域(首先搜索)包含本地名称
  • the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names 从最接近的封闭范围开始搜索的任何封闭函数的范围都包含非本地名称,也包含非全局名称
  • the next-to-last scope contains the current module's global names 倒数第二个范围包含当前模块的全局名称
  • the outermost scope (searched last) is the namespace containing built-in names 最外面的范围(最后搜索)是包含内置名称的名称空间

If a name is declared global, then all references and assignments go directly to the middle scope containing the module's global names. 如果名称被声明为全局名称,则所有引用和赋值将直接转到包含模块全局名称的中间范围。 Otherwise, all variables found outside of the innermost scope are read-only (an attempt to write to such a variable will simply create a new local variable in the innermost scope, leaving the identically named outer variable unchanged). 否则,在最内层作用域之外找到的所有变量都是只读的(尝试写入此类变量只会在最内层作用域内创建一个新的局部变量,而使名称相同的外层变量保持不变)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM