'if'评估中的Python逻辑错误

时间:2017-02-14 21:14:35

标签: python python-3.x docker python-3.5 ubuntu-16.04

我刚才遇到了最奇怪的错误。我没有机会完全调试它,但我想发布这个,看看是否有其他人有类似的问题。

问题

以下代码位于下载文件的函数中。如果最终文件存在,if语句逻辑旨在跳过下载步骤。

log.debug('force: {}, isfile: {}'.format(force, os.path.isfile(fasta_path)))
log.debug('if result: {}'.format(force or not os.path.isfile(fasta_path)))

if force or not os.path.isfile(fasta_path):
    # we don't have the file, so download it
    log.info('Downloading reference FASTA')
else:
    log.info('FASTA found--skipping download.')

运行时,会打印出以下内容:

[17-02-14 05:03:32 - __main__:119 - DEBUG] force: False, isfile: True
[17-02-14 05:03:32 - __main__:120 - DEBUG] if result: False
[17-02-14 05:03:32 - __main__:124 - INFO] Downloading reference FASTA

击穿

force变量旨在允许用户“强制”下载发生,而不管现有数据如何。正如您在输出中看到的那样,它是False

该文件的路径有效且文件存在,如输出中所示。

因此,if语句基本上是False or not True,它应该(并且也在输出中)评估为False;但是,True条件(Downloading reference)已执行。

我尝试过括号和一些最小的调试,但我找不到任何理由。例如,以下在python解释器中按预期工作:

if False or not True:
    print('hi')
else:
    print('bye')

环境

在docker容器中的ubuntu 16.04上使用Python 3.5会出现此问题。

2 个答案:

答案 0 :(得分:4)

如评论中@ user2357112所述,force很可能是一个字符串:

>>> print('if result: {}'.format("False" or not True))
if result: False
>>> "False" or not True
'False'
>>> type("False" or not True)
<class 'str'>
>>> bool("False" or not True)
True

这可能是第二个调试语句显示False的原因(因为它显示了字符串而不是布尔值)。您可以通过

进行测试
log.debug('if result: {}'.format(bool(force or not os.path.isfile(fasta_path))))

(预期输出if result: True)或

log.debug('if result: {}'.format(repr(force or not os.path.isfile(fasta_path))))

(预期输出if result: 'False' - 请注意引号表示它是一个字符串而不是布尔值)

修改说明:根据4.2. Boolean Operationx or y根据if x is false, then y, else x评估表达式False。由于根据4.1. Truth Value Testinge,只有空序列为'False'(在真值测试的上下文中),序列True'False' or x。因此'False'计算字符串x(独立于'False'的值)。在打印期间'False'不会被解释为布尔值。但是在if语句中,字符Truth已针对 CGPDFDocumentRef PDFref = loadPDFAtPath([filePath UTF8String]); CGPDFPageRef pageRef = CGPDFDocumentGetPage(PDFref, 1); NSString *encPath = [NSString stringWithFormat:@"%@-enc.pdf", filePath]; CFStringRef pathNew = (__bridge CFStringRef)encPath; CFURLRef url = CFURLCreateWithFileSystemPath(NULL, pathNew, kCFURLPOSIXPathStyle, 0); CFMutableDictionaryRef myDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef refPassword = (__bridge CFStringRef)password; CFStringRef creatorRef = (__bridge CFStringRef)@"CREATOR"; CFStringRef authorRef = (__bridge CFStringRef)@"TEST"; CFStringRef titleRef = (__bridge CFStringRef)@"TEST1"; CFDictionarySetValue(myDictionary, kCGPDFContextCreator, creatorRef); CFDictionarySetValue(myDictionary, kCGPDFContextAuthor, authorRef); CFDictionarySetValue(myDictionary, kCGPDFContextTitle, titleRef); CFDictionarySetValue(myDictionary, kCGPDFContextOwnerPassword, refPassword); CFDictionarySetValue(myDictionary, kCGPDFContextAllowsCopying, kCFBooleanFalse); CGRect prescriptionBounds = [PrescriptionMaker receiptBounds]; CGContextRef ref = CGPDFContextCreateWithURL(url, &prescriptionBounds, myDictionary); CGPDFContextBeginPage(ref, myDictionary); CGContextDrawPDFPage(ref, pageRef); CGPDFContextEndPage(ref); CGContextRelease(ref); ...

进行了测试

答案 1 :(得分:0)

FWIW,稍微修改一下代码,在Windows机器上运行,Python 2.6.5:

def stackOverflow(self, force, fasta_path):
    logging.info('force: {0}, isfile: {1}'.format(force, os.path.isfile(fasta_path)))
    logging.info('if result: {0}'.format(force or not os.path.isfile(fasta_path)))

if force or not os.path.isfile(fasta_path):
    # we don't have the file, so download it
    logging.info('Downloading reference FASTA')
else:
    logging.info('FASTA found--skipping download.')

这使得force的预期路径(“跳过下载”)为False且路径存在。电话是:

stackOverflow(False, r'C:\temp\pythoncode.txt')

将第一个参数作为字符串,正如评论所暗示的那样,将采用神秘的路径(“下载”)。

stackOverflow("False", r'C:\temp\pythoncode.txt')