【问题标题】:How to log errors in python when using the os module使用 os 模块时如何在 python 中记录错误
【发布时间】:2012-11-25 01:36:05
【问题描述】:

我正在尝试采用一种简单的方法来跟踪我想使用 python 中的 os 模块运行的定期 mysqldump 命令。我已经写了这个,但在测试中它不会引发异常,即使 mysqldump 命令以错误完成。我对python很陌生,所以我可能会非常接近这个,但我想我会尝试指出正确的方向。

db_dump = "mysqldump -u %s -p%s --socket=source_socket --databases %s | mysql -u %s -p%s   --socket=dest_socket" % (db_user, db_pass, ' '.join(db_list), db_user, db_pass)

try:
    os.system(db_dump)
except:
    logging.error("databases did not dump")
else:    
    logging.info("database dump complete")

【问题讨论】:

标签: python


【解决方案1】:

这就是我要做的。

import logging
import subprocess
log = logging.getLogger(__name__)

cmd = "mysqldump -u %s -p%s --socket=source_socket --databases %s | mysql -u %s -p%s " \
      "--socket=dest_socket" % (db_user, db_pass, ' '.join(db_list), db_user, db_pass)

process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE.PIPE)
stdout, stderr = process.communicate()
stdout = [x for x in stdout.split("\n") if x != ""]
stderr = [x for x in stderr.split("\n") if x != ""]

if process.returncode < 0 or len(stderr):
    for error in stderr:
        log.error(error)

【讨论】:

  • 这看起来比我在 Python 新手级别所准备的要高级得多。我非常感谢你的贡献,我期待着有一天我能更好地理解 Python 编程的复杂性。
  • 其实这还不错。我们所做的就是将您的命令推入子进程(这是一个更好的 os.system - 请参阅stackoverflow.com/questions/4813238/…)。一旦我们这样做了,我们就会等待结果(沟通)。然后将结果行再次拆分为行,验证我们得到了良好的回报,如果没有转储输出。
【解决方案2】:

os.system() 返回一个整数结果代码。返回 0 时,命令运行成功;当它返回一个非零值时,表示一个错误。

db_dump = "mysqldump -u %s -p%s --socket=source_socket --databases %s | mysql -u %s -p%s   --socket=dest_socket" % (db_user, db_pass, ' '.join(db_list), db_user, db_pass)

result = os.system(db_dump)
if 0 == result:
    logging.info("database dump complete")
else:
    logging.error("databases did not dump; result code: %d" % result)

和@COpython一样,我推荐使用subprocess。它比os.system() 稍微复杂一点,但灵活得多。使用os.system(),输出将发送到终端,但使用subprocess,您可以收集输出,以便搜索错误消息或其他内容。或者您可以丢弃输出。

【讨论】:

  • 感谢 steveha 的快速友好的回复。我试过了,它奏效了,但我会研究子流程,看看这最终是否会成为这个代码更好的解决方案。
  • 使用os.system(),您可以从您运行的程序中获得退出状态。您可以查看程序的“手册页”以查看它返回的错误。使用subprocess,您也可以获得退出状态,但使用os.system(),您只能获得这些;你不会得到例外。
【解决方案3】:

os.system 不是一种非常健壮或强大的调用系统命令的方法,我建议使用subprocess.check_output() 或subprocess.check_call

即,

>>> cmd = 'ls -l'
>>> badcmd = 'ls /foobar'
>>> subprocess.check_call(cmd.split())
0
>>> subprocess.check_call(badcmd.split())
ls: /foobar: No such file or directory
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 511, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ls', '/foobar']' returned non-zero exit status 1

【讨论】:

  • 感谢您的提示。我将研究子流程并尝试转换我的代码以在我熟悉它时使用它。
  • +1,但你不应该这样做cmd.split()。只需将cmd 作为字符串传递,subprocess 将考虑到引号,以适合平台的方式将其分解。 (当然,首先要有一个 args 列表而不是一个字符串——但如果你有一个字符串,不要调用 split 只是为了得到 args 的 list。)
  • @numb3rs1x:转换代码真的不需要太多 — 只需将每次使用的 os.system 替换为 subprocess.check_call。你甚至可以搜索并替换它。它与os.system 所做的不完全相同——相反,它将执行您期望os.system 执行的操作,这样会更好。 (如果您确实需要 os.system 所做的任何花哨的事情,例如在命令中传递 shell 表达式,请参阅 shell=True 标志。但您可能不需要。)
  • @abamert:我相信你需要split()这个命令,除非你用shell=True调用它
  • @abamert 我一直在玩子进程模块,它似乎是运行 shell 的方法。我正在为如何处理引发的异常而苦苦挣扎,因此它们会进入我选择的日志文件中。
猜你喜欢
  • 2010-09-07
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 2013-03-24
  • 2011-12-24
  • 1970-01-01
相关资源
最近更新 更多