Windows中

时间:2015-04-23 22:28:15

标签: python logging multiprocessing

我有一个CLI脚本,我用来将文件推送到s3桶中。 对于较大的文件,我将文件分成几部分并上传 在平行下。 (在这里粘贴代码结构。我试图制作一个极简主义的例子,但即便是60行)

def _upload_part(argFile, argBucket, max_attempts_limit, **core_chunk):
    #bunch of stuff
    pool = Pool(processes=parallel_processes)
    for i in range( chunk_amount ):
        #bunch of stuff
        pool.apply_async( _upload_for_multipart, [keyname, offset, mp, part_num, bytes] )
    pool.close()
    pool.join()

def _upload_for_multipart(keyname, offset, mp, part_num, bytes):
    #code to upload each part
    #log the status of each part to log files

def _get_logger( pdir, ldir, lname, level, fmt ):
    os.makedirs( logs_dir )
    logging.basicConfig(
        filename=os.path.join(logs_dir, lname),
        level=level,
        format=fmt
    )
    return logging.getLogger( lname )

#under main
if __name__ == "__main__":
    logneeds = dict( pdir=exec_dir, ldir='logs', lname='s3_cli.log', level='INFO',
                               fmt='%(asctime)s %(levelname)s: %(message)s' )
    logger = _get_logger(**logneeds)

上述代码结构在OSX和Linux中有效,但在Windows中失败。它说的 name 'logger' is not defined函数下的_upload_for_multipart。全局变量的方式之间存在差异 在Windows和基于unix的操作系统中解释?

修改:添加了工作示例here

1 个答案:

答案 0 :(得分:2)

您所看到的是在Windows与UNIX-y操作系统(或支持fork的任何操作系统)上创建子进程的方式不同。在Linux上,fork用于创建子进程,该进程在父进程的copy-on-write副本中创建子进程。这意味着父母中存在的所有变量都将出现在孩子身上。

但是,Windows不支持fork。为了创建子进程,它会生成一个全新的进程,然后重新导入子进程中父进程的__main__模块。在您的情况下,这意味着运行您的程序的脚本将在子项中导入。 logger的创建发生在父级的if __name__ == "__main__":后卫中,这意味着当孩子导入模块时会跳过它。 multiprocessing文档中有几个地方提到了这一点,我在this answer中明确列出了这些地方。

为了让logger存在于子节点中,它需要在模块的顶层创建(这意味着它每次导入时都会运行),或者您需要显式创建在所有子进程中,可能使用initializer的{​​{1}}参数:

multiprocessing.Pool