Python 中 Windows 中的全局变量范围
Scope of Global variables in Python in Windows
我有一个 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 的 OS?
中解释
编辑:添加了工作示例 here
您看到的是 child 进程在 Windows 与 UNIX-y OSes(或任何 OS 支持 fork
)。在 Linux 上,fork
用于创建 child 进程,它在 parent 进程的 copy-on-write 副本中创建 child。这意味着 parent 中存在的所有变量都将出现在 child.
中
Windows,但是不支持fork
。为了创建 child,它产生一个 brand-new 进程,然后 re-imports child 中 parent 的 __main__
模块。在您的情况下,这意味着脚本 运行 您的程序被导入 child。 logger
的创建发生在 parent 中的 if __name__ == "__main__":
守卫内部,这意味着当 child 导入模块时它会被跳过。 multiprocessing
文档中有几个地方提到了这一点,我在 .
中明确列出了这一点
为了让 logger
存在于 children 中,它需要在模块的 top-level 中创建(这意味着它会在您每次导入时运行它),或者您需要在所有 child 进程中显式创建它,也许使用 multiprocessing.Pool
:
的 initializer
参数
logger = None
def init_log():
global logger
logneeds = dict(pdir=exec_dir, ldir='logs', lname='s3_cli.log', level='INFO',
fmt='%(asctime)s %(levelname)s: %(message)s' )
logger = _get_logger(**logneeds)
def _upload_part(argFile, argBucket, max_attempts_limit, **core_chunk):
#bunch of stuff
pool = Pool(processes=parallel_processes, initializer=init_log)
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__":
init_log()
我有一个 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 的 OS?
编辑:添加了工作示例 here
您看到的是 child 进程在 Windows 与 UNIX-y OSes(或任何 OS 支持 fork
)。在 Linux 上,fork
用于创建 child 进程,它在 parent 进程的 copy-on-write 副本中创建 child。这意味着 parent 中存在的所有变量都将出现在 child.
Windows,但是不支持fork
。为了创建 child,它产生一个 brand-new 进程,然后 re-imports child 中 parent 的 __main__
模块。在您的情况下,这意味着脚本 运行 您的程序被导入 child。 logger
的创建发生在 parent 中的 if __name__ == "__main__":
守卫内部,这意味着当 child 导入模块时它会被跳过。 multiprocessing
文档中有几个地方提到了这一点,我在
为了让 logger
存在于 children 中,它需要在模块的 top-level 中创建(这意味着它会在您每次导入时运行它),或者您需要在所有 child 进程中显式创建它,也许使用 multiprocessing.Pool
:
initializer
参数
logger = None
def init_log():
global logger
logneeds = dict(pdir=exec_dir, ldir='logs', lname='s3_cli.log', level='INFO',
fmt='%(asctime)s %(levelname)s: %(message)s' )
logger = _get_logger(**logneeds)
def _upload_part(argFile, argBucket, max_attempts_limit, **core_chunk):
#bunch of stuff
pool = Pool(processes=parallel_processes, initializer=init_log)
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__":
init_log()