我正在使用属性类在S3
上为AWS
包装器类设置目标。如果还设置了infile,它应该只设置目的地。 (我已经意识到最好的解决办法就是将这个特定的课程分开,因为它试图做好两件事,而不是一件事。)
尽管如此,我很好奇导致这种递归堆栈溢出的原因。这是我班级的相关部分:
class S3Loads(PrettyStr):
def __init__(self,
infile=None,
s3_destination=None,
s3_bucket=config3.S3_BUCKET,
s3_credentials=config3.S3_INFO,
database_credentials=config3.REDSHIFT_POSTGRES_INFO_PROD):
"""
This class automates the upload of a file to AWS S3.
:param infile: A gzipped csv file
:param s3_destination: The path to the desired folder on S3. The file
will be named by joining the s3_destination and the infile name.
:param s3_bucket: The name of the bucket on S3
:return: None, but will write out to logging file.
"""
self.infile = infile
self.s3_destination = s3_destination
self.bucket_name = s3_bucket
self.s3_creds = s3_credentials
self.database_credentials = database_credentials
@property
def s3_destination(self):
return self.s3_destination
# TODO This is kicking off a recursive call, find out why
@s3_destination.setter
def s3_destination(self, s3_destination):
if self.infile:
if config3.SYSTEM == 'OSX':
self.s3_destination = path.join(
s3_destination,
self.infile.split('/')[-1]
)
elif config3.SYSTEM == 'Windows':
self.s3_destination = path.join(
s3_destination,
self.infile.split('\\')[-1]
)
else:
logging.warning('S3 Destination is being set to "None" due to '
'no infile being set. Please set an infile '
'and then set the S3 Destination.')
self.s3_destination = None
以下是正在进行此项测试的单元测试:
def test_setting_s3_destination_without_infile_set_it_to_none(self):
s3 = aws_utils.S3Loads()
def test_func():
s3.s3_destination = 'Some destination'
self.assertIsNone(s3.s3_destination)
def test_can_set_s3_destination_with_infile_specified(self):
s3 = aws_utils.S3Loads()
s3.infile='testfile.txt'
s3.destination='testloads/test1'
self.assertEqual(s3.destination, 'testloads/test1/testfile.txt')
我只是对导致递归的原因感到好奇。
答案 0 :(得分:1)
每次Python遇到self.s3_destination
时,都会调用s3_destination
函数。由于返回值self.s3_destination
引用了该属性,因此s3_destination
函数被递归调用,无限制地...
@property
def s3_destination(self):
return self.s3_destination
解决此问题的标准方法是使用私有属性self._s3_destination
:
class S3Loads(PrettyStr):
def __init__(self,...)
...
self._s3_destination = s3_destination
@property
def s3_destination(self):
return self._s3_destination
@s3_destination.setter
def s3_destination(self, value):
if self.infile:
if config3.SYSTEM == 'OSX':
self._s3_destination = path.join(
value,
self.infile.split('/')[-1]
)
elif config3.SYSTEM == 'Windows':
self._s3_destination = path.join(
value,
self.infile.split('\\')[-1]
)
else:
logging.warning('S3 Destination is being set to "None" due to '
'no infile being set. Please set an infile '
'and then set the S3 Destination.')
self._s3_destination = None