我有一个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
答案 0 :(得分:2)
您所看到的是在Windows与UNIX-y操作系统(或支持fork
的任何操作系统)上创建子进程的方式不同。在Linux上,fork
用于创建子进程,该进程在父进程的copy-on-write副本中创建子进程。这意味着父母中存在的所有变量都将出现在孩子身上。
fork
。为了创建子进程,它会生成一个全新的进程,然后重新导入子进程中父进程的__main__
模块。在您的情况下,这意味着运行您的程序的脚本将在子项中导入。 logger
的创建发生在父级的if __name__ == "__main__":
后卫中,这意味着当孩子导入模块时会跳过它。 multiprocessing
文档中有几个地方提到了这一点,我在this answer中明确列出了这些地方。
为了让logger
存在于子节点中,它需要在模块的顶层创建(这意味着它每次导入时都会运行),或者您需要显式创建在所有子进程中,可能使用initializer
的{{1}}参数:
multiprocessing.Pool