すべてのプロダクト
Search
ドキュメントセンター

MaxCompute:PyODPS FAQ

最終更新日:Jul 07, 2025

このトピックでは、PyODPS の使用時に関するよくある質問を紹介します。

問題カテゴリ

FAQ

PyODPS のインストール

モジュールのインポート

PyODPS の使用

PyODPS をインストールするときに「Warning: XXX not installed」というエラーメッセージが表示された場合はどうすればよいですか。

この問題は、コンポーネントが欠落していることが原因で発生します。エラーメッセージの XXX 情報から欠落しているコンポーネントの名前を特定し、pip コマンドを使用してインストールします。

PyODPS をインストールするときに「Project Not Found」というエラーメッセージが表示された場合はどうすればよいですか。

この問題の原因は次のとおりです。

  • エンドポイントの構成が正しくありません。ターゲットプロジェクトのエンドポイントに変更する必要があります。エンドポイントの詳細については、「エンドポイント」をご参照ください。

  • MaxCompute エントリオブジェクトのパラメーター位置が無効です。正しく入力されていることを確認してください。MaxCompute エントリオブジェクトパラメーターの詳細については、「PyODPSのインストール」をご参照ください。

PyODPS をインストールするときに「Syntax Error」というエラーメッセージが表示された場合はどうすればよいですか。

このエラーは、サポートされていない Python バージョンが原因で発生します。Python 2.5 以前は PyODPS ではサポートされていません。Python 2.7.6 以降のマイナーバージョン、Python 3.3 以降のマイナーバージョン、Python 2.6 など、PyODPS でサポートされているメインストリームバージョンを使用してください。

macOS で PyODPS をインストールするときに「Permission Denied」というエラーメッセージが表示された場合はどうすればよいですか。

PyODPS をインストールするには、sudo pip install pyodps コマンドを使用します。

macOS で PyODPS をインストールするときに「Operation Not Permitted」というエラーメッセージが表示された場合はどうすればよいですか。

このエラーは、システム整合性保護 (SIP) が原因で発生します。解決するには、デバイスを再起動し、起動プロセス中に [⌘] + [R] を押します。その後、ターミナルで以下のコマンドを実行します。

csrutil disable
reboot       

詳細については、「ルートで操作が許可されない - El Capitan (ルートレス無効)」をご参照ください。

from odps import ODPS コードを実行するときに「No Module Named ODPS」というエラーメッセージが表示された場合はどうすればよいですか。

このエラーは、ODPS パッケージを読み込むことができないことを示しています。考えられる原因は次のとおりです。

  • 原因 1: 複数の Python バージョンがインストールされています。

    解決策: 検索パス (通常は現在のディレクトリ) に、odps.py または init.py ファイルと odps という名前のディレクトリの両方が含まれていることを確認します。

    • 同じ名前のフォルダの場合は、フォルダ名を変更します。

    • 以前に odps という名前の Python パッケージをインストールした場合は、sudo pip uninstall odps を使用して削除できます。

  • 原因 2: Python 2 と Python 3 の両方のバージョンがインストールされています。

    解決策: デバイスに Python 2 または Python 3 のみがインストールされていることを確認します。

  • 原因 3: 現在の Python バージョンで PyODPS がインストールされていません。

    解決策: PyODPS をインストールします。インストール方法については、「PyODPS をインストールする」をご参照ください。

「from odps import ODPS」コードを実行するときに「Cannot Import Name ODPS」というエラーメッセージが表示された場合はどうすればよいですか。

現在の作業ディレクトリに [odps.py] という名前のファイルがあるかどうかを確認してください。そのようなファイルが存在する場合は、インポート操作を実行する前に名前を変更してください。

「from odps import ODPS」コードを実行するときに「Cannot Import Module odps」というエラーメッセージが表示された場合はどうすればよいですか。

このエラーは通常、PyODPS で発生した依存関係の問題が原因で発生します。リンクをクリックして PyODPS テクニカルサポート DingTalk グループに参加し、グループ管理者に連絡して支援を求めてください。

IPython または Jupyter Notebook で PyODPS を使用するときに「ImportError」というエラーメッセージが表示された場合はどうすればよいですか。

コードの先頭に from odps import errors を追加します。エラーが解決しない場合は、Ipython の依存関係が欠落している可能性があります。sudo pip install -U jupyter を実行することで、この問題を解決できます。

o.gettable('table_name').size の size フィールドは何を意味しますか。

SIZE フィールドは、テーブルの物理ストレージサイズを示します。

Tunnel エンドポイントを構成するにはどうすればよいですか。

options.tunnel.endpoint を使用して設定を構成できます。詳細については、「aliyun-odps-python-sdk」をご参照ください。

PyODPS で CPython を含むサードパーティパッケージを使用するにはどうすればよいですか。

CPython を含む wheel パッケージを生成することをお勧めします。詳細については、「MaxCompute で使用できる crcmod を作成する」をご参照ください。

PyODPS の DataFrame はどれだけのデータを処理できますか。また、テーブルのサイズに制限はありますか。

PyODPS にはテーブルのサイズの制限はありません。ローカル Pandas によって作成された DataFrame のサイズは、ローカルメモリのサイズによって制限されます。

DataFrame で max_pt を使用するにはどうすればよいですか。

odps.df.func モジュールを利用して、MaxCompute のビルトイン関数を呼び出します。

from odps.df import func
df = o.get_table('your_table').to_df()
df[df.ds == func.max_pt('your_project.your_table')]  # ds はパーティションフィールドです。     

PyODPS を使用してテーブルにデータを書き込む場合、open_writer() メソッドと write_table() メソッドの違いは何ですか。

write_table() を呼び出すたびにサーバー上に新しいファイルが作成されます。これは時間がかかり、生成されるファイルが多すぎるとクエリのパフォーマンスが低下し、メモリ不足が発生する可能性があります。これを軽減するために、複数のデータセットを同時に書き込むか、write_table() メソッドで Generator オブジェクトを使用することをお勧めします。write_table() メソッドの使用に関するガイダンスについては、「テーブルにデータを書き込む」をご参照ください。

open_writer() 関数は、デフォルトでブロックに書き込みます。

DataWorks の PyODPS ノードでクエリされるデータ量がローカル実行の結果よりも少ないのはなぜですか?

デフォルトでは、DataWorks でインスタンストンネルは有効になっていません。つまり、instance.open_reader は、最大 10,000 レコードを取得できる Result インターフェースを利用します。

インスタンストンネルが有効になると、reader.count を使用してレコード数を取得できます。すべてのデータを反復処理して取得するには、options.tunnel.limit_instance_tunnel = False を設定して制限を削除する必要があります。

DataFrame の実際のカウント数を取得する方法

  1. PyODPS をインストールした後、Python 環境で次のコマンドを実行して、MaxCompute テーブルを作成し、DataFrame を初期化します。

    iris = DataFrame(o.get_table('pyodps_iris'))        
  2. DataFrame に対して Count 操作を実行し、行の総数を取得します。

    iris.count()      
  3. DataFrame 操作はすぐに実行されず、ユーザーが明示的に Execute メソッドまたは即時実行メソッドを呼び出したときにのみ実行されます。Count メソッドが迅速に実行されるようにするには、次のコマンドを使用します。

    df.count().execute()    

DataFrame の実際の数を取得する方法については、「集計」をご参照ください。PyODPS メソッドの遅延操作の詳細については、「実行」をご参照ください。

PyODPS の使用時にエラーメッセージ「sourceIP is not in the white list」が表示された場合はどうすればよいですか?

PyODPS がアクセスする MaxCompute プロジェクトには、ホワイトリスト保護が適用されています。 プロジェクトオーナーに連絡して、デバイスを IP ホワイトリストに追加してもらってください。 IP ホワイトリスト情報の詳細については、「IP アドレスホワイトリストの管理」をご参照ください。

「from odps import options options.sql.settings」を使用して MaxCompute の実行環境の設定に失敗した場合の対処方法

  • 問題の説明

    PyODPS を使用して SQL を実行する場合、MaxCompute インスタンスを申請する前に、次のコードを使用して MaxCompute 実行環境を設定します。

    from odps import options
    options.sql.settings = {'odps.sql.mapper.split.size': 32}     // MaxCompute の実行環境を設定します。
    

    タスクを開始した後、6 つのマッパーのみが起動され、設定が適用されていないことが示されました。しかし、クライアントで set odps.stage.mapper.split.size=32 コマンドを実行すると、タスクは 1 分で完了しました。

  • 原因

    クライアントと PyODPS で設定されたパラメーターの間に不一致があります。クライアントは odps.stage.mapper.split.size パラメーターを使用しますが、PyODPS は odps.sql.mapper.split.size を使用します。

  • 解決策

    PyODPS のパラメーターを odps.stage.mapper.split.size に変更します。

DataFrame の head メソッドを呼び出したときにエラーメッセージ「IndexError: list index out of range」が表示されるのはなぜですか?

これは、list[index] に要素が含まれていないか、list[index] が許容範囲外であることが原因です。

Pandas DataFrame を MaxCompute にアップロードするときにエラーメッセージ「ODPSError」が表示された場合はどうすればよいですか?

  • 問題の説明

    Pandas DataFrame を MaxCompute にアップロードすると、次のエラーが返されます。

    ODPSError: ODPS entrance should be provided.
  • 原因

    このエラーは、グローバル MaxCompute オブジェクトエントリがないことが原因です。

  • 解決策

    • Room メカニズム %enter を使用すると、グローバルエントリが構成されます。

    • MaxCompute オブジェクトエントリで to_global メソッドを呼び出します。

    • パラメーター DataFrame(pd_df).persist('your_table', odps=odps) を使用します。

DataFrame を使用してテーブルにデータを書き込むときに「lifecycle is not specified in mandatory mode」というエラーメッセージが表示された場合はどうすればよいですか?

  • 問題の説明

    DataFrame を介してテーブルに書き込むときに、次のエラーが返されます。

    table lifecycle is not specified in mandatory mode
  • 原因

    テーブルのライフサイクルが設定されていません。

  • 解決策

    プロジェクトでは各テーブルのライフサイクルを設定する必要があるため、実行するたびに次の情報を設定する必要があります。

    from odps import options
    options.lifecycle = 7  # ライフサイクルの値をここに設定します。ライフサイクルの値は整数(日数)です。

PyODPS を使用してテーブルにデータを書き込むときに「サーバーからのデータストリームが破損している可能性があります」というエラーメッセージが表示された場合はどうすればよいですか?

このエラーは、ダーティデータが原因で発生します。 データ列の数がターゲットテーブルと一致しているかどうかを確認してください。

PyODPS を使用してテーブルからデータを読み取るときに「プロジェクトは保護されています」というエラーメッセージが表示された場合はどうすればよいですか?

プロジェクトのセキュリティポリシーにより、テーブルからのデータの読み取りが禁止されています。すべてのデータを使用するには、次の方法を検討してください。

  • プロジェクトオーナーに連絡して、例外ルールを追加してもらいます。

  • DataWorks またはその他のマスキングツールを使用してデータをマスキングし、保護されていないプロジェクトにエクスポートしてから読み取ります。

データの一部を表示するには、次の方法を使用します。

  • o.execute_sql('select * from <table_name>').open_reader() コマンドを実行して、指定されたテーブルからデータを取得できます。/* 指定されたテーブルからデータを取得できます。 */

  • o.get_table('<table_name>').to_df() を使用して、テーブルを DataFrame に変換できます。

PyODPS スクリプトタスクを実行するときに、エラーメッセージ「ConnectionError: timed out try catch exception」が断続的に表示される場合はどうすればよいですか?

このエラーの考えられる原因は次のとおりです。

  • 接続タイムアウト。 PyODPS のデフォルトのタイムアウトは 5 秒です。 問題を解決するには、次のいずれかのソリューションを使用します。

    • タイムアウト間隔を増やすには、スクリプトの先頭に次のコードを追加します。

      # 回避策
      from odps import options
      options.connect_timeout=30
    • 例外処理を実装してエラーをキャッチし、再試行を試みます。

  • サンドボックスの制限により、一部のマシンがネットワークにアクセスできない場合があります。 専用スケジューリングリソースグループを使用してタスクを実行し、この問題を解決します。

PyODPS を使用して get_sql_task_cost 関数を実行するときに「is not defined」というエラーメッセージが表示された場合はどうすればよいですか。

  • 問題の説明

    PyODPS を使用して get_sql_task_cost 関数を実行すると、次のエラーが返されます。

    NameError: name 'get_task_cost' is not defined.  // NameError: 'get_task_cost' という名前が定義されていません。
  • 解決策

    関数名が正しくありません。

  • 解決策

    get_sql_task_cost の代わりに execute_sql_cost を使用します。

PyODPS を使用してログを表示すると、漢字が自動的にエンコードされた表示に変換されます。ログに漢字を保持するにはどうすればよいですか?

print ("我叫 %s" % ('abc')) と同様の形式でコードを記述して漢字を入力します。これらの問題は Python 2 でのみ発生します。

options.tunnel.use_instance_tunnel = False を設定した場合、MaxCompute でフィールドが DATETIME 型として定義されているのに、SELECT 文を使用して取得したデータが STRING 型になるのはなぜですか。

Open_Reader を呼び出すと、PyODPS はデフォルトで従来の Result インターフェースを呼び出します。 この時、サーバーから取得されるデータは CSV フォーマットであるため、DATETIME は STRING 型になります。

options.tunnel.use_instance_tunnel = True を設定してインスタンストンネルを有効にすると、PyODPS はデフォルトでインスタンストンネルを使用するようになり、この問題が効果的に解決されます。

豊富な機能を実現するために Python 言語機能を使用する方法

  • Python 関数を作成する。

    2 つの点間の距離を計算するには、ユークリッド距離やマンハッタン距離など、さまざまな方法があります。一連の関数を定義し、計算中に特定の状況に応じて適切な関数を呼び出します。

    def euclidean_distance(from_x, from_y, to_x, to_y):
        return ((from_x - to_x) ** 2 + (from_y - to_y) ** 2).sqrt()
    
    def manhattan_distance(from_x, from_y, to_x, to_y):
       return (from_x - to_x).abs() + (from_y - to_y).abs()                      

    以下のように呼び出します。

    In [42]: df
         from_x    from_y      to_x      to_y
    0  0.393094  0.427736  0.463035  0.105007
    1  0.629571  0.364047  0.972390  0.081533
    2  0.460626  0.530383  0.443177  0.706774
    3  0.647776  0.192169  0.244621  0.447979
    4  0.846044  0.153819  0.873813  0.257627
    5  0.702269  0.363977  0.440960  0.639756
    6  0.596976  0.978124  0.669283  0.936233
    7  0.376831  0.461660  0.707208  0.216863
    8  0.632239  0.519418  0.881574  0.972641
    9  0.071466  0.294414  0.012949  0.368514
    
    In [43]: euclidean_distance(df.from_x, df.from_y, df.to_x, df.to_y).rename('distance')
       distance
    0  0.330221
    1  0.444229
    2  0.177253
    3  0.477465
    4  0.107458
    5  0.379916
    6  0.083565
    7  0.411187
    8  0.517280
    9  0.094420
    
    In [44]: manhattan_distance(df.from_x, df.from_y, df.to_x, df.to_y).rename('distance')
       distance
    0  0.392670
    1  0.625334
    2  0.193841
    3  0.658966
    4  0.131577
    5  0.537088
    6  0.114198
    7  0.575175
    8  0.702558
    9  0.132617                       
  • Python の条件文とループ文を使用する。

    ユーザーが計算したいテーブルがデータベースに格納されている場合、構成に従ってテーブルのフィールドを処理し、すべてのテーブルに対して UNION または JOIN 操作を実行する必要があります。 SQL で実装すると非常に複雑になりますが、DataFrame で処理するのは非常に簡単です。

    たとえば、1 つのテーブルに結合する必要がある 30 個のテーブルがある場合、SQL を使用すると、30 個のテーブルに対して UNION ALL 操作を実行する必要があります。 PyODPS を使用する場合、次のコードでタスクを完了できます。

    table_names = ['table1', ..., 'tableN']
    dfs = [o.get_table(tn).to_df() for tn in table_names]
    reduce(lambda x, y: x.union(y), dfs) 
    
    ## reduce 文は次のコードと同等です。
    df = dfs[0]
    for other_df in dfs[1:]:
        df = df.union(other_df)       

Pandas DataFrame バックエンドを使用してローカルの PyODPS プログラムをデバッグするにはどうすればよいですか。

次の 2 つの方法でローカルデバッグを実行します。初期化メソッド以外は、後続のコードは完全に一致します。

  • Pandas DataFrame を介して作成された PyODPS DataFrame は、Pandas を使用してローカル計算を実行できます。

  • MaxCompute テーブルを使用して作成された DataFrame は、MaxCompute で実行できます。

サンプルコードは次のとおりです。

df = o.get_table('movielens_ratings').to_df()
DEBUG = True
if DEBUG:
    df = df[:100].to_pandas(wrap=True)       

後続のコードがすべて記述されている場合、ローカルテストの速度は非常に速くなります。テストが完了したら、デバッグ値を False に変更すると、後続の計算を MaxCompute で実行できます。

MaxCompute Studio を使用してローカルの PyODPS プログラムをデバッグすることをお勧めします。

DataWorks PyODPS ノードでクエリされるデータ量がローカル実行の結果よりも少ないのはなぜですか。

パフォーマンスを最適化するために、各ループの結果を Dict データ構造を使用して取得し、ループの完了後に DataFrame オブジェクトにインポートすることをお勧めします。DataFrame オブジェクトコード df=XXX を外側のループに配置すると、ループ計算ごとに DataFrame オブジェクトが生成されます。その結果、ネストされたループの実行速度が遅くなります。

ローカルディレクトリへのデータのダウンロードを防ぐにはどうすればよいですか?

詳細については、「PyODPS ノードを使用してローカルディレクトリにデータをダウンロードして処理するか、オンラインでデータを処理する」をご参照ください。

どのようなシナリオで PyODPS データをオンプレミス マシンにダウンロードして処理できますか?

PyODPS データは、次の状況でローカル処理のためにダウンロードできます。

  • データ ボリュームが少ない場合。

  • 1 行が複数行になる操作や、Python 関数をデータの単一行に適用する操作の場合、PyODPS DataFrame を使用して MaxCompute の並列計算能力を効果的に活用します。

    たとえば、JSON 文字列データをキーと値のペアに基づいて行に展開するには、次のコードを使用します。

    In [12]: df
                   json
    0  {"a": 1, "b": 2}
    1  {"c": 4, "b": 3}
    
    In [14]: from odps.df import output
    
    In [16]: @output(['k', 'v'], ['string', 'int'])
        ...: def h(row):  # 関数 h を定義
        ...:     import json
        ...:     for k, v in json.loads(row.json).items():  # json データを展開
        ...:         yield k, v  # キーと値を返す
        ...:   
    
    In [21]: df.apply(h, axis=1)  # 関数 h を各行に適用
       k  v
    0  a  1
    1  b  2
    2  c  4
    3  b  3                          

DataFrame の実際のカウント数を取得するにはどうすればよいですか。

create table as select ... を使用して SQL の結果をテーブルとして保存し、table.open_reader で読み取ることができます。

組み込みオペレーターの使用が推奨されるのはなぜですか?

UDF は、計算中に組み込みオペレーターよりも実行速度が遅くなります。そのため、組み込みオペレーターを使用することをお勧めします。

数百万行のデータを処理する必要があり、行に対して UDF を使用する場合、実行時間が 7 秒から 27 秒に増加します。より大きなデータセットまたはより複雑な操作が必要な場合、時間の差はさらに大きくなる可能性があります。

DataFrame().schema.partitions を使用して取得したパーティションテーブルのパーティション値が空なのはなぜですか。

DataFrame は、パーティションフィールドと通常のフィールドを区別しないため、パーティションテーブルのパーティションフィールドは通常のフィールドとして扱われます。次のようにパーティションフィールドを除外します。

df = o.get_table().to_df()
# パーティションフィールドを除外
print(df[df.ds == ''].execute())

パーティションの設定方法またはパーティションからのデータの読み取り方法の詳細については、「テーブル」をご参照ください。

PyODPS を使用するときに「sourceIP is not in the white list」というエラーメッセージが表示された場合はどうすればよいですか。

詳細については、「PyODPS DataFrame でのデカルト積の処理」をご参照ください。

「from odps import options options.sql.settings」を使用して MaxCompute のランタイム環境を構成できない場合はどうすればよいですか。

詳細については、「PyODPS ノードを使用して Jieba に基づいて中国語テキストをセグメント化する」をご参照ください。

DataFrame の head メソッドを呼び出すと「IndexError:listindexoutofrange」というエラーメッセージが表示されるのはなぜですか。

デフォルトでは、PyODPS はインスタンスから読み取ることができるデータ量を制限しません。ただし、Tunnel コマンドを使用して保護されたプロジェクト用にダウンロードできるデータ量は制限されています。options.tunnel.limit_instance_tunnel を指定しない場合、制限は自動的に有効になり、ダウンロードできるデータレコード数は MaxCompute プロジェクトの構成に基づいて制限されます。ほとんどの場合、一度に最大 10,000 件のデータレコードをダウンロードできます。すべてのデータを反復的に取得する必要がある場合は、データ量のlimit を無効にする必要があります。Instance Tunnel を有効にし、limit を無効にするには、次の文を実行します。


Pandas DataFrame を MaxCompute にアップロードするときに「ODPSError」というエラーメッセージが表示された場合はどうすればよいですか。

このエラーは、アップロードされた Pandas DataFrame に NULL 値が含まれている場合に発生する可能性があります。解決するには、NULL 値を処理してから、Pandas DataFrame を MaxCompute にアップロードします。

DataFrame を使用してテーブルにデータを書き込むときに「lifecycle is not specified in mandatory mode」というエラーメッセージが表示された場合はどうすればよいですか。

PyODPS で新しいデータ型を有効にするには、次の手順に従います。

  • execute_sql メソッドで新しいデータ型を有効にすることで、o.execute_sql('set odps.sql.type.system.odps2=true;query_sql', hints={"odps.sql.submit.mode" : "script"}) を実行できます。

  • DataFrame を介して新しいデータ型を有効にするには (persist、execute、to_pandas など)、hints パラメーターを使用して設定します。図示されている設定方法は、単一のタスクに対してのみ有効です。

    from odps.df import DataFrame
    users = DataFrame(o.get_table('odps2_test'))
    users.persist('copy_test',hints={'odps.sql.type.system.odps2':'true'})
    # DataFrame を使用する場合、グローバルな効果が必要な場合は、オプションパラメータ options.sql.use_odps2_extension = True を設定します。
    

    DataFrame を使用する場合、グローバルな効果が必要な場合は、オプション パラメーター options.sql.use_odps2_extension = True を設定します。

PyODPS を使用してテーブルにデータを書き込むときに「Perhaps the datastream from server is crushed」というエラーメッセージが表示された場合はどうすればよいですか。

この問題を次の方法で解決します。

  • SDK をバージョン V0.8.4 以降にアップグレードします。

  • SQL に次の文を追加します。

    from odps.types import Decimal
    # Decimal の最大精度を 38 に設定します。
    Decimal._max_precision=38

PyODPS を使用してテーブルからデータを読み取るときに「Project is protected」というエラーメッセージが表示された場合はどうすればよいですか。

SQL タスクの実行速度が遅い場合、多くの場合 PyODPS には関連していません。次の手順を使用してトラブルシューティングを行います。

  1. ネットワークとサーバーの待機時間を確認する

    • タスクの送信に使用されるプロキシサーバーまたはネットワークリンクに遅延があるかどうかを確認します。

    • サーバーのタスクキューに遅延があるかどうかを判断します。

  2. データ読み取り効率を評価する

    SQL の実行に大量のデータの読み取りが含まれる場合、データのサイズが大きすぎること、またはデータシャードが多すぎることによって読み取り速度が低下していないかどうかを確認します。 次の手順で進めることができます。

    まず、タスクの送信とデータの読み取りを分離することを検討してください。run_sql を使用してタスクを送信し、instance.wait_for_success を使用して完了を待ちます。その後、instance.open_reader を使用してデータを読み取ります。 これにより、各操作で発生した遅延を特定できます。分割前後の例を以下に示します。

    • 分割前:

      with o.execute_sql('select * from your_table').open_reader() as reader:
          for row in reader:
              print(row)
    • 分割後:

      inst = o.run_sql('select * from your_table')
      inst.wait_for_success()
      with inst.open_reader() as reader:
          for row in reader:
              print(row)
  3. DataWorks ジョブステータスを確認する (該当する場合)

    DataWorks で送信されたジョブの場合、特に PyODPS のバージョンが 0.11.6 より前の場合、正しく送信されたが Logview を生成できない SQL タスクがあるかどうかを確認します。 これらのタスクは通常、execute_sql メソッドまたは run_sql メソッドを使用します。

  4. ローカル環境要因分析

    問題がローカル環境に関連しているかどうかを確認するには、デバッグログ機能を有効にすることをお勧めします。 PyODPS はすべてのリクエストとレスポンスを記録するため、ログを調べて遅延の原因を特定できます。

    以下に例を示します。

    import datetime
    import logging
    from odps import ODPS
    
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    o = ODPS(...)  # アカウント情報をここに入力します。環境が MaxCompute Entry を提供している場合は、無視します。
    # ローカル時間を表示して、ローカル操作が開始された時間を判断します
    print("Check time:", datetime.datetime.now())
    # タスクを送信する
    inst = o.run_sql("select * from your_table")

    標準出力は、ここに示されている結果のようになります。

    Check time: 2025-01-24 15:34:21.531330
    2025-01-24 15:34:21,532 - odps.rest - DEBUG - Start request.
    2025-01-24 15:34:21,532 - odps.rest - DEBUG - POST: http://service.<region>.maxcompute.aliyun.com/api/projects/<project>/instances
    2025-01-24 15:34:21,532 - odps.rest - DEBUG - data: b'<?xml version="1.0" encoding="utf-8"?>\n<Instance>\n  <Job>\n    <Priority>9</Priority>\n    <Tasks>\n      <SQL>\n        ....
    2025-01-24 15:34:21,532 - odps.rest - DEBUG - headers: {'Content-Type': 'application/xml'}
    2025-01-24 15:34:21,533 - odps.rest - DEBUG - request url + params /api/projects/<project>/instances?curr_project=<project>
    2025-01-24 15:34:21,533 - odps.accounts - DEBUG - headers before signing: {'Content-Type': 'application/xml', 'User-Agent': 'pyodps/0.12.2 CPython/3.7.12', 'Content-Length': '736'}
    2025-01-24 15:34:21,533 - odps.accounts - DEBUG - headers to sign: OrderedDict([('content-md5', ''), ('content-type', 'application/xml'), ('date', 'Fri, 24 Jan 2025 07:34:21 GMT')])
    2025-01-24 15:34:21,533 - odps.accounts - DEBUG - canonical string: POST
    
    application/xml
    Fri, 24 Jan 2025 07:34:21 GMT
    /projects/maxframe_ci_cd/instances?curr_project=maxframe_ci_cd
    2025-01-24 15:34:21,533 - odps.accounts - DEBUG - headers after signing: {'Content-Type': 'application/xml', 'User-Agent': 'pyodps/0.12.2 CPython/3.7.12', 'Content-Length': '736', ....
    2025-01-24 15:34:21,533 - urllib3.connectionpool - DEBUG - Resetting dropped connection: service.<region>.maxcompute.aliyun.com
    2025-01-24 15:34:22,027 - urllib3.connectionpool - DEBUG - http://service.<region>.maxcompute.aliyun.com:80 "POST /api/projects/<project>/instances?curr_project=<project> HTTP/1.1" 201 0
    2025-01-24 15:34:22,027 - odps.rest - DEBUG - response.status_code 201
    2025-01-24 15:34:22,027 - odps.rest - DEBUG - response.headers:
    {'Server': '<Server>', 'Date': 'Fri, 24 Jan 2025 07:34:22 GMT', 'Content-Type': 'text/plain;charset=utf-8', 'Content-Length': '0', 'Connection': 'close', 'Location': ....
    2025-01-24 15:34:22,027 - odps.rest - DEBUG - response.content: b''

    この出力は、コードがタスクを開始した時間 (2025-01-24 15:34:21.531)、リクエストを送信した時間 (2025-01-24 15:34:21.533)、およびサーバーのレスポンスを受信した時間 (2025-01-24 15:34:22.027) を示しており、各ステージの期間を明確にしています。