You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器日志未显示全部输出消息技术求助

Docker容器中Python脚本自定义print输出丢失问题

问题说明

开发了一款基于TLAPI的量化数据同步脚本,本地运行时自定义print语句正常输出,但部署到Docker容器后,docker logs仅能看到TLAPI库的日志,自定义打印内容完全缺失。已排除镜像缓存问题,纯print测试脚本在Docker中可正常输出,怀疑是TLAPI库修改了stdout导致。

脚本代码

import pandas as pd
import requests
import os
from dotenv import load_dotenv
from tradelocker import TLAPI
import schedule
import datetime
import logging
import time
import pytz
import sys

data_path = './data'
est = pytz.timezone('US/Eastern')
time_now = datetime.datetime.now(est)
load_dotenv()

tl = TLAPI(environment = "https://demo.tradelocker.com", 
           username = os.getenv("TL_USER"), 
           password = os.getenv("TL_PASS"), 
           server = os.getenv("TL_SERVER"))

def read_tickers(file_name):
  try:
    with open(file_name, 'r') as file:
      tickers = [line.strip() for line in file.readlines()]
      return tickers
  except FileNotFoundError:
    print(time_now, f"Ticker file {file_name} not found.")
    return []

tickers = read_tickers('tl_tickers.txt')

def initial_download_check():
  if not os.path.isdir(data_path):
    print(time_now, "Data folder absent")
    os.mkdir(data_path)
    return True
  if not os.listdir(data_path):
    print(time_now, "Data path is empty")
    return True

def initial_download(symbol, resolution, length):
  instrument_id = tl.get_instrument_id_from_symbol_name(symbol)
  df = tl.get_price_history(instrument_id, 
                            resolution=resolution, 
                            start_timestamp=0, 
                            end_timestamp=0,
                            lookback_period=length)
  df.set_index("t", inplace=True)
  return df

def latest_bar(symbol, resolution, timestamp):
  instrument_id = tl.get_instrument_id_from_symbol_name(symbol)
  df = tl.get_price_history(instrument_id, 
                            resolution=resolution, 
                            start_timestamp=timestamp, 
                            end_timestamp=0)
  df.set_index("t", inplace=True)
  return df

def is_market_open():
  five_pm = time(17, 0)
  if time.weekday() == 4 and time.time() >= five_pm:
    return False    
  if time.weekday() == 5:
    return False
  if time.weekday() == 6 and time.time() < five_pm:
    return False
  return True

def update_data():
  if is_market_open():
    for ticker in tickers:
      data = pd.read_feather(f"data/{ticker}_1H_10D_tl.feather")
      last_candle = data.tail(1)
      last_timestamp = data.index[-1]
      new_candle = latest_bar(ticker, "1H", int(last_timestamp))
      new_timestamp = new_candle.index[-1]
    if last_candle.equals(new_candle):
      print(time_now, f"No new data found for {ticker}")
    else:
      print(time_now, f"New data found for {ticker}, updating...")
      data = data.append(new_candle)
      data.drop(df.index[0], inplace=True)

print(time_now, "Starting...")

if initial_download_check():
  print(time_now, "Starting initial download...")
  for ticker in tickers:
    print(time_now, f"Downloading initial data for {ticker}...")
    df = initial_download(ticker, '1H', "10D")
    df.to_feather(f"data/{ticker}_1H_10D_tl.feather")
else:
  print(time_now, "Skipping initial download.")

print(time_now, "Scheduling update every 1 hour...")
schedule.every(1).hour.do(update_data)

while True:
  schedule.run_pending()
  time.sleep(1)

本地运行日志

[INFO 2024-08-26 12:56:29,617 tradelocker_api.__init__:143]: Initialized TLAPI with log_level='debug' self._LOGGING_FORMAT='[%(levelname)s %(asctime)s %(module)s.%(funcName)s:%(lineno)d]: %(message)s'
[INFO 2024-08-26 12:56:31,108 tradelocker_api._auth_with_password:779]: Successfully fetched authentication tokens
[DEBUG 2024-08-26 12:56:31,108 utils.wrapper:83]: **** CALLING get_all_accounts(<tradelocker.tradelocker_api.TLAPI object at 0x7f043872a1b0>)
[DEBUG 2024-08-26 12:56:32,980 utils.wrapper:94]: **** RETURN from get_all_accounts(<tradelocker.tradelocker_api.TLAPI object at 0x7f043872a1b0>):
[DEBUG 2024-08-26 12:56:32,980 tradelocker_api._set_account_id_and_acc_num:253]: Neither account_id nor acc_num specified, using the first account
[DEBUG 2024-08-26 12:56:32,980 tradelocker_api._set_account_id_and_acc_num:261]: Logging in using the first account, account_id: 000000, acc_num: 1
2024-08-26 14:56:29.616411-04:00 Starting...
2024-08-26 14:56:29.616411-04:00 Skipping initial download.
2024-08-26 14:56:29.616411-04:00 Scheduling update every 1 hour...

Docker容器运行日志

[INFO 2024-08-26 18:44:45,995 tradelocker_api.__init__:143]: Initialized TLAPI with log_level='debug' self._LOGGING_FORMAT='[%(levelname)s %(asctime)s %(module)s.%(funcName)s:%(lineno)d]: %(message)s'
[INFO 2024-08-26 18:44:46,287 tradelocker_api._auth_with_password:779]: Successfully fetched authentication tokens
[DEBUG 2024-08-26 18:44:46,287 utils.wrapper:83]: **** CALLING get_all_accounts(<tradelocker.tradelocker_api.TLAPI object at 0x7ee72d9b2330>)
[DEBUG 2024-08-26 18:44:47,901 utils.wrapper:94]: **** RETURN from 
[1 rows x 5 columns]
[DEBUG 2024-08-26 18:44:47,901 tradelocker_api._set_account_id_and_acc_num:253]: Neither account_id nor acc_num specified, using the first account
[DEBUG 2024-08-26 18:44:47,901 tradelocker_api._set_account_id_and_acc_num:261]: Logging in using the first account, account_id: 000000, acc_num: 1

Dockerfile内容

FROM python:3

WORKDIR /usr/src/app

COPY reqs_docker_prod.txt ./
RUN pip install --no-cache-dir -r reqs_docker_prod.txt

COPY . .

CMD [ "python", "main.py"]

解决方法

1. 禁用Python输出缓冲

启动容器时添加环境变量,强制Python实时输出内容:

docker run -e PYTHONUNBUFFERED=1 myusername/app:1.1

2. 替换print为logging模块

使用Python标准日志库替代print,确保和TLAPI日志流一致:

# 初始化logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')

# 替换所有print语句
logging.info(f"{time_now} Starting...")
logging.info(f"{time_now} Skipping initial download.")

3. 强制刷新stdout

在每个print语句后手动刷新输出流:

print(time_now, "Starting...")
sys.stdout.flush()

4. 调整TLAPI日志级别

初始化TLAPI时降低日志级别,减少日志干扰:

tl = TLAPI(environment = "https://demo.tradelocker.com", 
           username = os.getenv("TL_USER"), 
           password = os.getenv("TL_PASS"), 
           server = os.getenv("TL_SERVER"),
           log_level='info')

内容的提问来源于stack exchange,提问作者so1120

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:00:55