气流Python脚本退出,任务退出,返回代码-9,如何解决?

时间:2019-08-12 14:34:16

标签: python memory airflow

我不知道此错误的含义,有人说这是内存错误,我不确定,因为该错误不是显式的,但是我加载的表很大,有100万行。

这是我的脚本中发生错误的部分:

# snapshot_profiles
  df_snapshot_profiles = load_table('snapshot_profiles', conn)

  def return_key(x, key):
    try:
      return (x[key])
    except:
      return (None)

  df_snapshot_profiles['is_manager'] = df_snapshot_profiles["payload"].apply(
      lambda x: return_key(x, 'is_manager'))
  df_snapshot_profiles_actual = df_snapshot_profiles.loc[:,
                                                         ['profile_id', 'date']]
  df_snapshot_profiles_actual.sort_values(['profile_id', 'date'], inplace=True)
  df_snapshot_profiles_actual = df_snapshot_profiles_actual.groupby(
      'profile_id').max().reset_index()
  df_snapshot_profiles.drop(
      ['id', 'payload', 'version', 'company_id', 'inserted_at', 'updated_at'],
      axis=1,
      inplace=True)
  df_snapshot_profiles_actual = df_snapshot_profiles_actual.merge(
      df_snapshot_profiles, on=['date', 'profile_id'], how='left')
  df_snapshot_profiles_actual.drop('date', axis=1, inplace=True)

  df = df.merge(df_snapshot_profiles_actual, on='profile_id', how='left')
  del df_snapshot_profiles

  # Excluir do banco empresas com menos de dois usuários (Empresas de testes)
  df_companies = df.groupby('company_name').count()
  df_companies.reset_index(inplace=True)
  df_companies = df_companies[df_companies['user_id'] > 2]
  df_companies.sort_values('user_id', ascending=False)

  companies = list(df_companies.company_name)

  df['check_company'] = df['company_name'].apply(lambda x: 'T'
                                                 if x in companies else 'F')
  df = df[df['check_company'] == 'T']
  df.drop('check_company', axis=1, inplace=True)

这是加载表并打印内存使用情况的脚本:

def usage():
  process = psutil.Process(os.getpid())
  return process.memory_info()[0] / float(2**20)


def load_table(table, conn):
    print_x(f'{usage()} Mb')
    print_x(f'loading table {table}')
    cursor = conn.cursor()
    cursor.execute(f'''select * from {ORIGIN_SCHEMA}.{table};''')
    df = cursor.fetchall()
    cursor.execute(f'''
        select column_name from information_schema.columns where table_name = '{table}';
    ''')
    labels = cursor.fetchall()
    label_list = []
    for label in labels:
        label_list.append(label[0])
    df = pd.DataFrame.from_records(df, columns=label_list)
    return (df)

有没有一种方法可以通过减少内存使用量或其他方式来避免错误?

2 个答案:

答案 0 :(得分:1)

好吧。应该是内存不足的问题。您可以扩展内存或将部分工作移出核心(以批处理模式加载工作)

  • 如果有预算,请扩展内存。 1百万行*每列可怕的字符串长度(1000)= 1M * 1K = 1G内存,用于数据加载。合并数据帧或转换数据帧时,您需要额外的内存,因此16G应该可以。

  • 如果您是专家,请尝试使用核心模式,即在硬盘上工作。

    • dask是核心模块中的熊猫之一。计算机处于批处理模式。速度慢,但仍然可以工作。
    • 将数据库用于某些功能工作。我发现大多数数据库可以完成类似熊猫的工作,尽管需要复杂的SQL代码。

祝你好运。 如果您喜欢我的回答,请投票。

答案 1 :(得分:0)

我通过实现服务器端游标并按块获取信息来解决此问题,如下所示:

  serverCursor = conn.cursor("serverCursor")
  serverCursor.execute(f'''select * from {ORIGIN_SCHEMA}.{table};''')

  df = []
  while True:
    records = serverCursor.fetchmany(size=50000)
    df = df + records
    if not records:
      break
  serverCursor.close()