python -c 妙用


前言

python -c 命令還是有用的哈

正文

python的 -c 可以在命令行中調用 python 代碼, 實際上 -c 就是 command 的意思

官方文檔中解釋為(節選自: python docs):

Execute the Python code in command. command can be one or more statements separated by newlines, with significant leading whitespace as in normal module code.

If this option is given, the first element of sys.argv will be "-c" and the current directory will be added to the start of sys.path (allowing modules in that directory to be imported as top level modules).

Raises an auditing event cpython.run_command with argument command.

簡單來說, 就是 python -c 可以在命令行中執行 python 代碼, 跟把代碼放置在 .py 文件中然后運行這個文件比無明顯差別, 我們來測試一下

python -c "print('TTXT')"

隨后正確輸出了 TTXT

需要注意的是, python -c 后必須跟一個字符串, 因此必須帶上引號, 而且在要執行的代碼中也不要重疊, 這樣會引發錯誤, 這是因為 python 認不出該到哪里結尾, 例如

python -c "print("TTXT")"

這樣就會報錯, 輸出

Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'TTXT' is not defined

我們一般可以使用三引號來標示需要執行的代碼, 例如

python -c '''print("TTXT")'''

這樣還有一個好處就是也可以執行多行的代碼, 例如

python -c '''
import arrow    
print(arrow.now())
'''

這樣也是可以的, 也可以定義並調用函數

python -c '''
def a():        
    print(111)
a()
'''

當然也是可以導入自定義的模塊或者已經安裝的包的

妙用

那么 -c 有什么妙用呢? 這個要具體問題具體分析, 比如說我在開發中要使用一個第三方包 patool, 項目在 github, 這個包作用是根據格式解壓壓縮文件, 但是在調用時發生總是會報找不到 patoollib 模塊的錯誤

官方給的例子如下

import patoolib
patoolib.extract_archive("archive.zip", outdir="/tmp")

排查發現, 該模塊的起始文件最上面寫定了python的地址, 導致運行時強制指定了python路徑而沒有使用自己的虛擬環境, 因為 /usr/bin/python 沒有安裝 patool 包所以報錯找不到

py文件節選

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (C) 2010-2015 Bastian Kleineidam
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
patool [global-options] {extract|list|create|diff|search|formats} [sub-command-options] <command-args>
"""

def main():
    """Parse options and execute commands."""
    try:
        argparser = create_argparser()
        args = argparser.parse_args()
        if args.command is None:
            # Python 3.3.1 under linux allows an empty command somehow
            argparser.error("too few arguments")
        # run subcommand function
        res = globals()["run_%s" % args.command](args)
    except KeyboardInterrupt:
        log_error("aborted")
        res = 1
    except Exception:
        log_internal_error()
        res = 2
    return res


if __name__ == '__main__':
    sys.exit(main())

似乎只能將包的源代碼修改, 實際上只要把第一行刪除即可, 但是考慮到Docker部署, 就沒有更好的辦法了嗎? 使用 python -c 即可完美解決

我們使用 python -c 在命令行中使用我們指定的 python 去執行模塊, 就會使py文件中指定的不生效, 所以調用改成如下即可

code = f"import patoolib; patoolib.extract_archive('{file}', outdir='{unfile}')"
proc = await asyncio.create_subprocess_exec(sys.executable, '-c', code)
await proc.wait()

這樣就可以完美的解決問題了, 不用修改原來包的代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM