簡體   English   中英

Python 函數返回不一致的結果

[英]Python function returns inconsistent results

我編寫了一個腳本來列出 Amazon Web Services 中的 EC2 實例。 它將結果寫入匯合。 但它的行為很奇怪。

我在 Windows 10 上。第一次打開 powershell 終端並運行它時,它會報告 AWS 帳戶中正確的服務器數量。

下次我運行它時(根本不改變任何東西)它會使結果翻倍。 每次使用相同的參數再次運行它時,它都會報告相同的錯誤(加倍)數量。

這是列出實例的函數,這是我認為問題所在,但我很難找到它:

def list_instances(aws_account, aws_account_number, interactive, regions, fieldnames, show_details):
    today, aws_env_list, output_file, output_file_name, fieldnames = initialize(interactive, aws_account)     options = arguments()     instance_list = ''     session = ''     ec2 = ''     account_found = ''     PrivateDNS = None     block_device_list = None     instance_count = 0     account_type_message = ''     profile_missing_message = ''     region = ''
    # Set the ec2 dictionary
    ec2info = {}
    # Write the file headers
    if interactive == 1:
        with open(output_file, mode='w+') as csv_file:
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=',', lineterminator='\n')
            writer.writeheader()
            if 'gov' in aws_account and not 'admin' in aws_account:
                try:
                    session = boto3.Session(profile_name=aws_account,region_name=region)
                    account_found = 'yes'
                except botocore.exceptions.ProfileNotFound as e:
                    message = f"An exception has occurred: {e}"
                    account_found = 'no'
                    banner(message)
            else:
                try:
                    session = boto3.Session(profile_name=aws_account,region_name=region)
                    account_found = 'yes'
                except botocore.exceptions.ProfileNotFound as e:
                    message = f"An exception has occurred: {e}"
                    account_found = 'no'
                    banner(message)
    print(Fore.CYAN)
    report_gov_or_comm(aws_account, account_found)
    print(Fore.RESET)
    for region in regions:
        if 'gov' in aws_account and not 'admin' in aws_account:
            try:
                session = boto3.Session(profile_name=aws_account,region_name=region)
            except botocore.exceptions.ProfileNotFound as e:
                profile_missing_message = f"An exception has occurred: {e}"                 account_found = 'no' pass else: try:                 session = boto3.Session(profile_name=aws_account,region_name=region)                 account_found = 'yes' except botocore.exceptions.ProfileNotFound as e:                 profile_missing_message = f"An exception has occurred: {e}" pass try:             ec2 = session.client("ec2") except Exception as e: pass
    # Loop through the instances
    try:
        instance_list = ec2.describe_instances()
    except Exception as e:
        pass
    try:
        for reservation in instance_list["Reservations"]:
            for instance in reservation.get("Instances", []):
                instance_count = instance_count + 1
                launch_time = instance["LaunchTime"]
                launch_time_friendly = launch_time.strftime("%B %d %Y")
                tree = objectpath.Tree(block_devices = set(tree.execute('$..BlockDeviceMappings['Ebs']['VolumeId']'))
                if block_devices:
                    block_devices = list(block_devices)
                    block_devices = str(block_devices).replace('[','').replace(']','').replace("'",'')
                else:
                    block_devices = None
                    private_ips =  set(tree.execute('$..PrivateIpAddress'))
                    if private_ips:
                        private_ips_list = list(private_ips)                         private_ips_list = str(private_ips_list).replace('[','').replace(']','').replace(''','')
                    else:
                        private_ips_list = None
                        type(private_ips_list)
                        public_ips =  set(tree.execute('$..PublicIp'))
                        if len(public_ips) == 0:
                            public_ips = None
                        if public_ips:
                            public_ips_list = list(public_ips)
                            public_ips_list = str(public_ips_list).replace('[','').replace(']','').replace("'",'')
                        else:
                            public_ips_list = None
                        if 'KeyName' in instance:
                            key_name = instance['KeyName']
                        else:
                            key_name = None
                            name = None
                        if 'Tags' in instance:
                            try:
                                tags = instance['Tags']
                                name = None
                                for tag in tags:
                                    if tag["Key"] == "Name":
                                        name = tag["Value"]
                                if tag["Key"] == "Engagement" or tag["Key"] == "Engagement Code":
                                    engagement = tag["Value"]
                            except ValueError:
                                print("Instance: %s has no tags" % instance_id
                                pass
                    if 'VpcId' in instance:
    vpc_id = instance['VpcId'] else:                         vpc_id = None if 'PrivateDnsName' in instance:                         private_dns = instance['PrivateDnsName'] else:                         private_dns = None if 'Platform' in instance:                         platform = instance['Platform'] else:                         platform = None print(f"Platform: {platform}")                     ec2info[instance['InstanceId']] = { 'AWS Account': aws_account, 'Account Number': aws_account_number, 'Name': name, 'Instance ID': instance['InstanceId'], 'Volumes': block_devices, 'Private IP': private_ips_list, 'Public IP': public_ips_list, 'Private DNS': private_dns, 'Availability Zone': instance['Placement']['AvailabilityZone'], 'VPC ID': vpc_id, 'Type': instance['InstanceType'], 'Platform': platform, 'Key Pair Name': key_name, 'State': instance['State']['Name'], 'Launch Date': launch_time_friendly                     } with open(output_file,'a') as csv_file:                         writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=',', lineterminator='\n')                         writer.writerow({'AWS Account': aws_account, "Account Number": aws_account_number, 'Name': name, 'Instance ID': instance["InstanceId"], 'Volumes': block_devices,  'Private IP': private_ips_list, 'Public IP': public_ips_list, 'Private DNS': private_dns, 'Availability Zone': instance['Placement']['AvailabilityZone'], 'VPC ID': vpc_id, 'Type': instance["InstanceType"], 'Platform': platform, 'Key Pair Name': key_name, 'State': instance["State"]["Name"], 'Launch Date': launch_time_friendly})
    if show_details == 'y' or show_details == 'yes': for instance_id, instance in ec2info.items(): if account_found == 'yes': print(Fore.RESET + "-------------------------------------") for key in [ 'AWS Account', 'Account Number', 'Name', 'Instance ID', 'Volumes', 'Private IP', 'Public IP', 'Private DNS', 'Availability Zone', 'VPC ID', 'Type', 'Platform', 'Key Pair Name', 'State', 'Launch Date'                                 ]: print(Fore.GREEN + f"{key}: {instance.get(key)}") print(Fore.RESET + "-------------------------------------") else: pass                     ec2info = {} with open(output_file,'a') as csv_file:                         csv_file.close() except Exception as e: pass if profile_missing_message == '*':         banner(profile_missing_message) print(Fore.GREEN)     report_instance_stats(instance_count, aws_account, account_found) print(Fore.RESET + '\n') return output_file

這是上下文的整個代碼的粘貼: aws_ec2_list_instances.py

第一次從命令行運行它時,它會報告 EC2 中正確的服務器總數(可以在 AWS 控制台中驗證):

----------------------------------------------------------
There are: 51 EC2 instances in AWS Account: company-lab.
----------------------------------------------------------

下一次它以絕對沒有改變的情況運行時,它會報告這個總數:

----------------------------------------------------------
There are: 102 EC2 instances in AWS Account: company-lab.
----------------------------------------------------------

您實際上只是向上箭頭命令,它會使結果加倍。 當它寫入 confluence 時,您可以看到列出了重復的服務器。 每次向上箭頭再次運行它時,它都會這樣做,但總數不正確(102 個服務器)。

如果您關閉 powershell 命令行並再次打開,它將返回報告正確結果(51 個服務器),這與您在 AWS 控制台中看到的內容相對應。 這到底是怎么回事? 為什么要這樣做,我該如何解決問題?

這相當神秘! 我認為如果不訪問您的環境,我將無法對其進行調試。 我的建議是您使用pdb來嘗試弄清楚instance_count如何增加超過 51。我建議添加import pdb; pdb.set_trace() import pdb; pdb.set_trace()在第 210 行,即for reservation in instance_list["Reservations"]: 然后,您可以每次通過循環檢查instance_count的值,查看instance_list["Reservations"]是否實際上以某種方式具有重復數據等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM