Python-Cooker

ๅ†™pythonๅฆ‚็ƒนๅฐ้ฒœ

ๅ…ณไบŽpythontutorๅตŒๅ…ฅ

่€ƒ่™‘ๅˆฐๆ›ดๆ–นไพฟๆŸฅ็œ‹python็š„ๆ‰ง่กŒ่ฟ‡็จ‹๏ผŒ่ฟ™้‡Œ่€ƒ่™‘ๅฐ†pythontutorๆŽฅๅ…ฅ

pythontutor้กน็›ฎ่งฃๅ‰–

่ฏดๆ˜Ž

ๆœฌๆ–‡ไธป่ฆๅ‰–ๆžไธ€ไธ‹pythontutor็š„้กน็›ฎ็ป“ๆž„ไธŽไธšๅŠกๆต็จ‹๏ผŒๅนถ็กฎๅฎšๅŽ้ข็š„็›ธๅ…ณไปฃ็ ๅฏ่ง†ๅŒ–็š„ไฝฟ็”จๆ–นๆณ•

ๆ€ปไฝ“็ป“ๆž„ๅ›พ

pythontutor็ป“ๆž„ๅ›พ

                                                                                                                                                  โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ 
                                                                                                                                                  โ”ƒ                              _                    _                            โ”ƒ 
                                                                                                                                                  โ”ƒ                _ __  __ _ __| |____ _ __ _ ___   (_)___ ___ _ _                โ”ƒ 
                                                                                                                                                  โ”ƒ               | '_ \/ _` / _| / / _` / _` / -_)_ | (_-</ _ \ ' \               โ”ƒ 
                                                                                                                                                  โ”ƒ               | .__/\__,_\__|_\_\__,_\__, \___(_)/ /__/\___/_||_|              โ”ƒ 
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“                                                               โ”ƒ               |_|                    |___/     |__/                            โ”ƒ 
โ”ƒ       ___      _   _               _____     _             ___                  โ”ƒ                                                               โ”ƒ                                                                                โ”ƒ 
โ”ƒ      | _ \_  _| |_| |_  ___ _ _   |_   _|  _| |_ ___ _ _  | __|_ _____ __       โ”ƒ                                                               โ”ƒ   {                                                                            โ”ƒ 
โ”ƒ      |  _/ || |  _| ' \/ _ \ ' \    | || || |  _/ _ \ '_| | _|\ \ / -_) _|      โ”ƒ                                                               โ”ƒ     "name": "v5-unity",                                                        โ”ƒ 
โ”ƒ      |_|  \_, |\__|_||_\___/_||_|   |_| \_,_|\__\___/_|   |___/_\_\___\__|      โ”ƒ                                                               โ”ƒ     "version": "1.0.0",                                                        โ”ƒ 
โ”ƒ           |__/                                                                  โ”ƒ                                                               โ”ƒ     "description": "OPT v5",                                                   โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "main": "bundle.js",                                                       โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "repository": "https://github.com/pgbovine/OnlinePythonTutor",             โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "license": "BSD-3-Clause",                                                 โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "scripts": {                                                               โ”ƒ 
โ”ƒ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                     โ”ƒ                                                               โ”ƒ       "start": "python bottle_server.py",                                      โ”ƒ 
โ”ƒ  โ”‚                        โ”‚                                                     โ”ƒ                                                               โ”ƒ       "py3start": "python3 bottle_server.py",                                  โ”ƒ 
โ”ƒ  โ”‚    botter_server.py    โ”‚                                                     โ”ƒ                                                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ซ       "webpack": "webpack --devtool sourcemap --progress --colors --watch",    โ”ƒ 
โ”ƒ  โ”‚      get_py_exec       โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                        โ”ƒ                                                     โ”‚         โ”ƒ       "production-build": "rm -f build/* && webpack && python                  โ”ƒ 
โ”ƒ  โ”‚                        โ”‚            โ”‚                                        โ”ƒ                                                     โ”‚         โ”ƒ   add_cache_busting_query_strings.py"                                          โ”ƒ 
โ”ƒ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚                                        โ”ƒ                                                     โ”‚         โ”ƒ     },                                                                         โ”ƒ 
โ”ƒ                                        โ”‚                                        โ”ƒ                                                     โ”‚         โ”ƒ     "dependencies": {                                                          โ”ƒ 
โ”ƒ                                        โ”‚           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”ƒ                                                     โ”‚         โ”ƒ       "css-loader": "",                                                        โ”ƒ 
โ”ƒ                                        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ                         โ”‚  โ”ƒ                                   npm run production-build    โ”ƒ       "fs-extra": "^6.0.1",                                                    โ”ƒ 
โ”ƒ                                                    โ”‚      pg_logger.py       โ”‚  โ”ƒ                                                     โ”‚         โ”ƒ       "json-stable-stringify": "^1.0.1",                                       โ”ƒ 
โ”ƒ                                                    โ”‚  exec_script_str_local  โ”‚  โ”ƒ                                                     โ”‚         โ”ƒ       "on-build-webpack": "^0.1.0",                                            โ”ƒ 
โ”ƒ                                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                         โ”‚  โ”ƒ                                                     โ”‚         โ”ƒ       "pixelmatch": "^4.0.2",                                                  โ”ƒ 
โ”ƒ                                        โ”‚           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”ƒ                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚         โ”ƒ       "puppeteer": "^1.5.0",                                                   โ”ƒ 
โ”ƒ                                        โ”‚                                        โ”ƒ                  โ”‚                         โ”‚        โ”‚         โ”ƒ       "script-loader": "",                                                     โ”ƒ 
โ”ƒ                                        โ”‚                                        โ”ƒ                  โ”‚     /visualize.html     โ”‚        โ”‚         โ”ƒ       "style-loader": "",                                                      โ”ƒ 
โ”ƒ                                        โ”‚                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ   visualize.bundle.js   โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”ƒ       "ts-loader": "^3.5.0",                                                   โ”ƒ 
โ”ƒ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”‚                       โ”‚                โ”ƒ                  โ”‚                         โ”‚                  โ”ƒ       "url-loader": ""                                                         โ”ƒ 
โ”ƒ  โ”‚                         โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜               return trace info        โ”ƒ                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ”ƒ     }                                                                          โ”ƒ 
โ”ƒ  โ”‚      pg_logger.py       โ”‚                         {code: '', trace: []}      โ”ƒ                                                               โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ–ฒโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› 
โ”ƒ  โ”‚   PGLogger._runscript   โ”‚                                   โ”‚                โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ  โ”‚                         โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                    โ”ƒ                                                                                                   webpack                                        
โ”ƒ                                                                                 โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ                                                                                 โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ                                                                                 โ”ƒ                                                                โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ปโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ                  _                  _                  __ _         _          โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ      __ __ _____| |__ _ __  __ _ __| |__  __ ___ _ _  / _(_)__ _   (_)___      โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ      \ V  V / -_) '_ \ '_ \/ _` / _| / /_/ _/ _ \ ' \|  _| / _` |_ | (_-<      โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ       \_/\_/\___|_.__/ .__/\__,_\__|_\_(_)__\___/_||_|_| |_\__, (_)/ /__/      โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ                      |_|                                   |___/ |__/          โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ   entry: {                                                                     โ”ƒ
โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›                                                                โ”ƒ       'visualize': "./js/visualize.ts",                                        โ”ƒ
                                                                                                                                                   โ”ƒ       'recorder': "./js/recorder.ts",                                          โ”ƒ
                                                                                                                                                   โ”ƒ       'render-trace': "./js/render-trace.ts",                                  โ”ƒ
                                                                                                                                                   โ”ƒ       'opt-live': "./js/opt-live.ts",                                          โ”ƒ
                                                                                                                                                   โ”ƒ       'iframe-embed': "./js/iframe-embed.ts",                                  โ”ƒ
                                                                                                                                                   โ”ƒ       'index': "./js/index.ts",                                                โ”ƒ
                                                                                                                                                   โ”ƒ       'composingprograms': "./js/composingprograms.ts",                        โ”ƒ
                                                                                                                                                   โ”ƒ       'csc108h': "./js/csc108h.ts",                                            โ”ƒ
                                                                                                                                                   โ”ƒ       'pytutor-embed': "./js/pytutor-embed.ts",                                โ”ƒ
                                                                                                                                                   โ”ƒ   },                                                                           โ”ƒ
                                                                                                                                                   โ”ƒ                                                                                โ”ƒ
                                                                                                                                                   โ”ƒ   output: {                                                                    โ”ƒ
                                                                                                                                                   โ”ƒ       path: __dirname + "/build/",                                             โ”ƒ
                                                                                                                                                   โ”ƒ       // TODO: use 'bundle.[hash].js' for fingerprint hashing                  โ”ƒ
                                                                                                                                                   โ”ƒ       // to create unique filenames for releases:                              โ”ƒ
                                                                                                                                                   โ”ƒ       // https://webpack.github.io/docs/long-term-caching.html                 โ”ƒ
                                                                                                                                                   โ”ƒ       filename: "[name].bundle.js",                                            โ”ƒ
                                                                                                                                                   โ”ƒ       sourceMapFilename: "[file].map",                                         โ”ƒ
                                                                                                                                                   โ”ƒ   },                                                                           โ”ƒ
                                                                                                                                                   โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›

iframeไฝฟ็”จ็คบไพ‹

ไฝฟ็”จbottleๅ†™webๆœๅŠก

from bottle import route, get, request, run, template, static_file

try:
    import StringIO  # NB: don't use cStringIO since it doesn't support unicode!!!
except:
    import io as StringIO  # py3
import json
import pg_logger


@route('/web_exec_<name:re:.+>.py')
@route('/LIVE_exec_<name:re:.+>.py')
@route('/viz_interaction.py')
@route('/syntax_err_survey.py')
@route('/runtime_err_survey.py')
@route('/eureka_survey.py')
@route('/error_log.py')
def dummy_ok(name=None):
    return 'OK'


@route('/<filepath:path>')
def index(filepath):
    return static_file(filepath, root='.')


# Note that this will run either Python 2 or 3, depending on which
# version of Python you used to start the server, REGARDLESS of which
# route was taken:
@route('/web_exec_py2.py')
@route('/web_exec_py3.py')
@route('/LIVE_exec_py2.py')
@route('/LIVE_exec_py3.py')
def get_py_exec():
    out_s = StringIO.StringIO()

    def json_finalizer(input_code, output_trace):
        ret = dict(code=input_code, trace=output_trace)
        json_output = json.dumps(ret, indent=None)
        out_s.write(json_output)

    options = json.loads(request.query.options_json)

    pg_logger.exec_script_str_local(request.query.user_script,
                                    request.query.raw_input_json,
                                    options['cumulative_mode'],
                                    options['heap_primitives'],
                                    json_finalizer)

    return out_s.getvalue()


if __name__ == "__main__":
    run(host='localhost', port=8003, reloader=True)

่ฟ™้‡Œๅฏไปฅๅ‘็Žฐ๏ผŒไฝœ่€…็š„่ทฏ็”ฑๅŸบๆœฌๆฑ‡่šๅœจget_py_exec, ่ฟ›ๅ…ฅๅŽๆ‰ง่กŒexec_script_str_local

pg_logger.pyไป‹็ป

python tutorๆ ธๅฟƒ็ฑป

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                        
โ”‚                   โ”‚                                                        
โ”‚ botter_server.py  โ”‚                                                        
โ”‚    get_py_exec    โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                         
โ”‚                   โ”‚              โ”‚                                         
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜              โ”‚                                         
                                   โ”‚                                         
                                   โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ                         โ”‚
                                                  โ”‚      pg_logger.py       โ”‚
                                                  โ”‚  exec_script_str_local  โ”‚
                                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                         โ”‚
                                      โ”‚           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                      โ”‚                                      
                                      โ”‚                                      
                                      โ”‚                                      
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”‚                                      
โ”‚                         โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                      
โ”‚      pg_logger.py       โ”‚                                                  
โ”‚   PGLogger._runscript   โ”‚                                                  
โ”‚                         โ”‚                                                  
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                  

็ปงๆ‰ฟ่‡ชBdb

class PGLogger(bdb.Bdb):

ๅˆๅง‹ๅŒ–็›ธๅ…ณ

    def __init__(
            self,
            cumulative_mode,
            heap_primitives,
            show_only_outputs,
            finalizer_func,
            disable_security_checks=False,
            allow_all_modules=False,
            crazy_mode=False,
            custom_modules=None,
            separate_stdout_by_module=False,
            probe_exprs=None):

่ฐƒ็”จๅ‡ฝๆ•ฐ

def exec_script_str_local(
        script_str,
        raw_input_lst_json,
        cumulative_mode,
        heap_primitives,
        finalizer_func,
        probe_exprs=None,
        allow_all_modules=False):
    # ๆ ธๅฟƒ่ฟ่กŒ่ฟ‡็จ‹่ฎฐๅฝ•็ฑป
    logger = PGLogger(
        cumulative_mode,
        heap_primitives,
        False,
        finalizer_func,
        disable_security_checks=True,
        allow_all_modules=allow_all_modules,
        probe_exprs=probe_exprs
    )

    # TODO: refactor these NOT to be globals
    global input_string_queue
    input_string_queue = []
    if raw_input_lst_json:
        # TODO: if we want to support unicode, remove str() cast
        input_string_queue = [str(e) for e in json.loads(raw_input_lst_json)]

    try:
        logger._runscript(script_str)
    except bdb.BdbQuit:
        pass
    finally:
        return logger.finalize()

่ฟ”ๅ›žๆ•ฐๆฎ็คบไพ‹

{
  "code": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())",
  "trace": [
    {
      "line": 5,
      "event": "step_line",
      "func_name": "<module>",
      "globals": {},
      "ordered_globals": [],
      "stack_to_render": [],
      "heap": {},
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 19,
      "event": "step_line",
      "func_name": "<module>",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [],
      "heap": {},
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 10,
      "event": "call",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601"
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 11,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601"
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 12,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "name",
            "Pat"
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 13,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 14,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 14,
      "event": "return",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000,
            "__return__": null
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary",
            "__return__"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 20,
      "event": "step_line",
      "func_name": "<module>",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 16,
      "event": "call",
      "func_name": "salutation",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [
        {
          "func_name": "salutation",
          "is_parent": false,
          "frame_id": 2,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ]
          },
          "ordered_varnames": [
            "self"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "salutation_f2"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 17,
      "event": "step_line",
      "func_name": "salutation",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [
        {
          "func_name": "salutation",
          "is_parent": false,
          "frame_id": 2,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ]
          },
          "ordered_varnames": [
            "self"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "salutation_f2"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 17,
      "event": "return",
      "func_name": "salutation",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [
        {
          "func_name": "salutation",
          "is_parent": false,
          "frame_id": 2,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "__return__": "Professor Pat"
          },
          "ordered_varnames": [
            "self",
            "__return__"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "salutation_f2"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 20,
      "event": "return",
      "func_name": "<module>",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\nProfessor Pat\n"
    }
  ]
}

ๅ‚่€ƒ่ต„ๆ–™

ๅบ•ๅฑ‚ๆŠฝ่ฑก

่™šๆ‹Ÿๅ†…ๅญ˜็ฎก็†

็ฑปๅž‹็ณป็ปŸ

ๅŸบ็ก€ๅ†…็ฝฎ็ฑปๅž‹

้›†ๅˆ็ฑปๅž‹

่‡ชๅฎšไน‰็ฑปๅž‹

็ผ–็จ‹่ฏญ่จ€่ฏญๆณ•ๆฆ‚่ฟฐ

่ฏๆณ•ๅ…ณ้”ฎๅญ—ๆ‰ซ็›ฒ

้€ป่พ‘ๅˆคๆ–ญไธŽๅพช็Žฏ

่ฏญๅฅไธŽ่กจ่พพๅผ

ไปฃ็ ่ดจ้‡๏ผšๅผ‚ๅธธใ€ๆต‹่ฏ•ไธŽๆ—ฅๅฟ—

่ฐƒ่ฏ•๏ผšbdbไธŽpdb

Pythonๆ ‡ๅ‡†ๅบ“ไธญ็š„Debuggerๆก†ๆžถbdbๆจกๅ—

ๆไพ›ๅŸบๆœฌ็š„่ฐƒ่ฏ•ๅŠŸ่ƒฝ๏ผŒๅฆ‚่ฎพ็ฝฎๆ–ญ็‚นใ€็ฎก็†Debugger็š„ๆ‰ง่กŒ็ญ‰ใ€‚

bdbๆจกๅ—็š„็ป„ๆˆ๏ผš

  • ๅผ‚ๅธธbdb.BdbQuit(Exception)
  • ็ฑปclass bdb.Breakpoint
  • ็ฑปclass bdb.Bdb(skip=None)
  • ๆต‹่ฏ•็ฑปclass Tdb(Bdb)

Error rendering admonishment

Failed with: TOML parsing error: expected an equals, found a newline at line 1 column 5

Original markdown input:

```admonish tip title='pdbๆ˜ฏbdb็š„ๅญ็ฑป
Bdbๆ˜ฏPython Debugger็š„ๅŸบ็ฑป๏ผŒๅฎž้™…ไฝฟ็”จ็š„Python Debuggerๆ˜ฏๅ…ถๅญ็ฑปPdbใ€‚
```
  • def set_trace(): ่ฏฅๆ–นๆณ•็”จไปฅๅผ€ๅฏ่ฐƒ่ฏ•ใ€‚
  • def checkfuncname(b, frame)
  • def effective(file, line, frame): ่ฏฅๆ–นๆณ•็”จไปฅ็กฎๅฎš็›ธๅฏนไบŽ่ฏฅfile็š„่ฏฅline๏ผŒๅ“ชไธชBreakpointๆœ‰ๆ•ˆใ€‚

Python Debugger่ฐƒ่ฏ•ๅ™จ

Python็š„ไธ€ๆฌพไบคไบ’ๅผ่ฐƒ่ฏ•ๅ™จ๏ผŒๅฏไปฅ่ฎพ็ฝฎๆ–ญ็‚นใ€ๅ•ๆญฅ่ฐƒ่ฏ•ใ€ๆฃ€ๆŸฅๅ †ๆ ˆใ€‚

pdbๆจกๅ—ไธญ็š„Pdb็ฑป

class Pdb(bdb.Bdb, cmd.Cmd)

ๅฏๅŠจ่ฐƒ่ฏ•็š„ๆ–นๅผ

  • Python่งฃ้‡Šๅ™จ็š„ๅ‘ฝไปค่กŒไธญ
# python3
import pdb

pdb.run('mymodule.mytest()')
  • ่ฐƒ่ฏ•ไธ€ไธช่„šๆœฌๆ–‡ไปถ
python3 -m pdb myscript.py
  • ๅœจPythonๆบไปฃ็ ไธญ
import pdb;

pdb.set_trace()
# ...
pdb.pm()
# ่ฟ›ๅ…ฅ่ฐƒ่ฏ•ๆจกๅผ

่ฐƒ่ฏ•ๅ‘ฝไปค

  • h,ๅธฎๅŠฉ

  • w,ๆ‰“ๅฐๅ †ๆ ˆ

  • d,ๅœจๅ †ๆ ˆไธญ็งปๅŠจๅˆฐไธ‹ไธ€็บงframe

  • u,ๅœจๅ †ๆ ˆไธญ็งปๅŠจๅˆฐไธŠไธ€็บงframe

  • b lineno|func,ๅœจๆŒ‡ๅฎšไฝ็ฝฎๅค„่ฎพ็ฝฎๆ–ญ็‚น

  • tbreak lineno|func,ๅœจๆŒ‡ๅฎšไฝ็ฝฎๅค„่ฎพ็ฝฎไธดๆ—ถๆ–ญ็‚น๏ผŒๆ‰ง่กŒๆ—ถๆ–ญ็‚นๅช็”Ÿๆ•ˆไธ€ๆฌก

  • disable bp_number,็ฆ็”จๆŒ‡ๅฎšๆ–ญ็‚น

  • enable bp_number,ๅฏๅŠจๆŒ‡ๅฎšๆ–ญ็‚น

  • ignore bp_number count,ๅฟฝ็•ฅๆŒ‡ๅฎšๆ–ญ็‚นcountๆฌก

  • cl,ๆธ…้™คๆ‰€ๆœ‰ๆ–ญ็‚น

  • cl lineno|func|bp_number,ๆธ…้™คๆŒ‡ๅฎšไฝ็ฝฎๅค„็š„ๆ–ญ็‚น

  • s,ๆ‰ง่กŒๅฝ“ๅ‰่กŒ๏ผŒไธ่ฟ›ๅ…ฅ่ขซ่ฐƒ็”จ็š„ๅ‡ฝๆ•ฐ

  • n,ๆ‰ง่กŒๅˆฐไธ‹ไธ€่กŒ๏ผŒๅฆ‚ๆžœ่ฐƒ็”จไบ†ๅ…ถไป–ๅ‡ฝๆ•ฐๅˆ™ๆ‰ง่กŒ่ขซ่ฐƒ็”จๅ‡ฝๆ•ฐ

  • unt,ๆ‰ง่กŒ...็›ดๅˆฐ

  • r,ๆ‰ง่กŒๅˆฐreturn

  • c,็ปง็ปญๆ‰ง่กŒ

  • j lineno,่ทณ่ฝฌๅˆฐๆŒ‡ๅฎš่กŒ

  • l,

  • ll,

  • a,

  • p ,

  • pp ,

  • whatis ,

  • source ,

  • display ,

  • undisplay ,

  • run,้‡ๅฏไปฃ็ ็š„ๆ‰ง่กŒ

  • restart,ๅŒrun

  • q,้€€ๅ‡บ่ฐƒ่ฏ•ๆจกๅผ

  • alias myname my_command,่ฎพ็ฝฎๅˆซๅ

  • ้€šๅธธๅœจ.pdbrcๆ–‡ไปถไธญ

  • unalias myname,ๅ–ๆถˆๅˆซๅ

  • interact

ๅ‚่€ƒ่ต„ๆบ๏ผš

่ฎพ่ฎกๆŠฝ่ฑก

็ผ–็จ‹่Œƒๅผ

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅ‡ฝๆ•ฐๅผ็ผ–็จ‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

้ขๅ‘ๅฏน่ฑก็ผ–็จ‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๆณ›ๅž‹็ผ–็จ‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

่ฎพ่ฎกๆจกๅผ

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

้กน็›ฎๆจกๅ—็ฎก็†ๅŠๆ‰ฉๅฑ•

ๅฏนไบŽไธ€้—จ็ผ–็จ‹่ฏญ่จ€๏ผŒๆ˜ฏๅฆ่ƒฝๅคŸๆˆไธบๅทฅ็จ‹ๅŒ–ๅผ€ๅ‘ๅทฅๅ…ท็š„ไธป่ฆๆ ‡ๅ‡†ๅœจไบŽไธค็‚น๏ผš

  1. ๅŒ…็ฎก็†ใ€ๆจกๅ—็ฎก็†
  2. ๆ‰ฉๅฑ•ๅทฅๅ…ทๆ˜ฏๅฆๆ–นไพฟๅŠ ๅ…ฅ

่ฟ™้‡Œ้ขๅŒ…ๅซไธ€ไบ›้€š็”จ็š„่ฎพ่ฎกๆŠฝ่ฑก๏ผŒๅ› ๆญคไธ“้—จไฝœไธบๅ•็‹ฌ็š„ไธ€ๅฑ‚ใ€‚

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

Pythonๆจกๅ—็ณป็ปŸ

package->module->method

package

ไธ€็งๅฏๅŒ…ๅซๅญๆจกๅ—ๆˆ–้€’ๅฝ’ๅœฐๅŒ…ๅซๅญๅŒ…็š„ Python moduleใ€‚ไปŽๆŠ€ๆœฏไธŠ่ฏด๏ผŒๅŒ…ๆ˜ฏๅธฆๆœ‰ path ๅฑžๆ€ง็š„ Python ๆจกๅ—ใ€‚

ไผ ็ปŸๅž‹็š„ package๏ผŒไพ‹ๅฆ‚ๅŒ…ๅซๆœ‰ไธ€ไธช init.py ๆ–‡ไปถ็š„็›ฎๅฝ•ใ€‚

PEP 420 ๆ‰€ๅผ•ๅ…ฅ็š„ไธ€็งไป…่ขซ็”จไฝœๅญๅŒ…็š„ๅฎนๅ™จ็š„ package๏ผŒๅ‘ฝๅ็ฉบ้—ดๅŒ…ๅฏไปฅๆฒกๆœ‰ๅฎžไฝ“่กจ็คบ็‰ฉ๏ผŒๅ…ถๆ่ฟฐๆ–นๅผไธŽ regular package ไธๅŒ๏ผŒๅ› ไธบๅฎƒไปฌๆฒกๆœ‰ init.py ๆ–‡ไปถใ€‚

module

ๆญคๅฏน่ฑกๆ˜ฏ Python ไปฃ็ ็š„ไธ€็ง็ป„็ป‡ๅ•ไฝใ€‚ๅ„ๆจกๅ—ๅ…ทๆœ‰็‹ฌ็ซ‹็š„ๅ‘ฝๅ็ฉบ้—ด๏ผŒๅฏๅŒ…ๅซไปปๆ„ Python ๅฏน่ฑกใ€‚ๆจกๅ—ๅฏ้€š่ฟ‡ importing ๆ“ไฝœ่ขซๅŠ ่ฝฝๅˆฐ Python ไธญใ€‚

ไธ€ไธชๅ‘ฝๅ็ฉบ้—ด๏ผŒๅ…ถไธญๅŒ…ๅซ็”จไบŽๅŠ ่ฝฝๆจกๅ—็š„็›ธๅ…ณๅฏผๅ…ฅไฟกๆฏใ€‚ๆ˜ฏ importlib.machinery.ModuleSpec ็š„ๅฎžไพ‹ใ€‚

- [importlib --- import ็š„ๅฎž็Žฐ โ€” Python 3.10.5 ๆ–‡ๆกฃ](https://docs.python.org/zh-cn/3/library/importlib.html#importlib.machinery.ModuleSpec)
ๅ…ณไบŽๆจกๅ—ๅฏผๅ…ฅ็ณป็ปŸ็›ธๅ…ณ็Šถๆ€็š„่ง„่Œƒใ€‚้€šๅธธ่ฟ™ๆ˜ฏไฝœไธบๆจกๅ—็š„ __spec__ ๅฑžๆ€งๆšด้œฒๅ‡บๆฅใ€‚ 
ๅœจไปฅไธ‹ๆ่ฟฐไธญ๏ผŒๆ‹ฌๅท้‡Œ็š„ๅๅญ—็ป™ๅ‡บไบ†ๆจกๅ—ๅฏน่ฑกไธญ็›ดๆŽฅๅฏ็”จ็š„ๅฑžๆ€งใ€‚
ๆฏ”ๅฆ‚ module.__spec__.origin == module.__file__ใ€‚ 
ไฝ†ๆ˜ฏ่ฏทๆณจๆ„๏ผŒ่™ฝ็„ถ ๅ€ผ ้€šๅธธๆ˜ฏ็›ธ็ญ‰็š„๏ผŒไฝ†ๅฎƒไปฌๅฏไปฅไธๅŒ๏ผŒๅ› ไธบไธคไธชๅฏน่ฑกไน‹้—ดๆฒกๆœ‰่ฟ›่กŒๅŒๆญฅใ€‚
ๅ› ๆญค __path__ ๆœ‰ๅฏ่ƒฝๅœจ่ฟ่กŒๆ—ถๅš่ฟ‡ๆ›ดๆ–ฐ๏ผŒ่€Œ่ฟ™ไธไผš่‡ชๅŠจๅๆ˜ ๅœจ __spec__.submodule_search_locations ไธญใ€‚

method

MRO

ๆจกๅ—็š„็”จๆ„๏ผšๅˆ†ๅ‰ฒไธŽๅฏผๅ…ฅ

ๅ‚่€ƒ่ต„ๆบ

6. ๆจกๅ— โ€” Python 3.10.5 ๆ–‡ๆกฃ

  1. ๆ–‡ไปถๅณๆจกๅ—๏ผšไธบๅฎž็Žฐๅˆ‡ๅˆ†้œ€ๆฑ‚๏ผŒPython ๆŠŠๅ„็งๅฎšไน‰ๅญ˜ๅ…ฅไธ€ไธชๆ–‡ไปถ๏ผŒๅœจ่„šๆœฌๆˆ–่งฃ้‡Šๅ™จ็š„ไบคไบ’ๅผๅฎžไพ‹ไธญไฝฟ็”จใ€‚่ฟ™ไธชๆ–‡ไปถๅฐฑๆ˜ฏ ๆจกๅ— ๏ผ›ๆจกๅ—ไธญ็š„ๅฎšไน‰ๅฏไปฅ ๅฏผๅ…ฅ ๅˆฐๅ…ถไป–ๆจกๅ—ๆˆ– ไธป ๆจกๅ—๏ผˆๅœจ้กถๅฑ‚ๅ’Œ่ฎก็ฎ—ๅ™จๆจกๅผไธ‹๏ผŒๆ‰ง่กŒ่„šๆœฌไธญๅฏ่ฎฟ้—ฎ็š„ๅ˜้‡้›†๏ผ‰ใ€‚

ๅœจๆจกๅ—่ฟ™ไธ€็‚น๏ผŒpythonใ€rustๅ’Œgoๅ„ๆœ‰ไธๅŒ

  • python็š„ไปฃ็ ็ฎก็†ๆœ€ๅฐๅ•ไฝๆ˜ฏๆจกๅ—
  • rustไปฃ็ ็ฎก็†ๆœ€ๅฐๅ•ไฝไนŸๆ˜ฏๆจกๅ—๏ผŒไฝ†ๆ˜ฏๅฎƒ่ฟ˜ๆไพ›ไบ†ไธ€ไธชๅ…ณ้”ฎๅญ—mod่ฎฉไธ€ไธชๆ–‡ไปถ้‡Œ้ขๅŒ…ๅซๅคšไธชๆจกๅ—ใ€‚rust็š„crateๅ…ถๅฎžๆ˜ฏ'ๆ ‡ๅ‡†'ๅŒ…๏ผŒ็”ฑไธ€็ณปๅˆ—ๅทฒๅ‘ๅธƒใ€็‰ˆๆœฌๅŒ–ใ€่ขซๅˆ†ๅ‘็š„ๅŒ…ๆž„ๆˆใ€‚ๅฏไปฅ็›ดๆŽฅไปŽ็‰ˆๆœฌๆŽงๅˆถไป“ๅบ“ๆˆ–crate.ioไธ‹่ฝฝๆจกๅ—ใ€‚
  • go็š„moduleๅ’Œpackage็š„ๅ…ณ็ณปๅˆ™ไธŽๅ‰ไธค่€…ๅ่ฟ‡ๆฅ๏ผšๆจกๅ—็”ฑไธ€็ณปๅˆ—ๅทฒๅ‘ๅธƒใ€็‰ˆๆœฌๅŒ–ใ€่ขซๅˆ†ๅ‘็š„ๅŒ…ๆž„ๆˆใ€‚ๅฏไปฅ็›ดๆŽฅไปŽ็‰ˆๆœฌๆŽงๅˆถไป“ๅบ“ๆˆ–ๆจกๅ—ไปฃ็†ๆœๅŠกๅ™จไธ‹่ฝฝๆจกๅ—ใ€‚
  1. ๆ–‡ไปถๅๅณๆจกๅ—ๅ๏ผšๆจกๅ—ๆ˜ฏๅŒ…ๅซ Python ๅฎšไน‰ๅ’Œ่ฏญๅฅ็š„ๆ–‡ไปถใ€‚ๅ…ถๆ–‡ไปถๅๆ˜ฏๆจกๅ—ๅๅŠ ๅŽ็ผ€ๅ .py ใ€‚
  2. ๅœจๆจกๅ—ๅ†…้ƒจ๏ผŒ้€š่ฟ‡ๅ…จๅฑ€ๅ˜้‡ name ๅฏไปฅ่Žทๅ–ๆจกๅ—ๅ๏ผˆๅณๅญ—็ฌฆไธฒ๏ผ‰ใ€‚
  3. ๅ…ณไบŽๆจกๅ—ๅ‘ฝๅ็ฉบ้—ด๏ผšๆฏไธชๆจกๅ—ๆœ‰ๅ„่‡ชๆ–‡ไปถ่Œƒๅ›ดๅ†…็š„ๅ…จๅฑ€ๅ‘ฝๅ็ฉบ้—ด(global namespace)
  4. ๆจกๅ—้กถ้ƒจๅผ•ๅ…ฅ็š„ๅ…ถไป–ๆจกๅ—ๅœจๆ–‡ไปถๅ†…ๅ…จๅฑ€ๅฏ็”จ๏ผŒๅœจๅ‡ฝๆ•ฐใ€็ฑป็ญ‰ๅ†…้ƒจๅผ•ๅ…ฅ็š„๏ผŒๅช่ƒฝๅœจๅ†…้ƒจไฝฟ็”จ
  5. ๅ…ณไบŽfrom module_name import *: ๅฏผๅ…ฅๆ‰€ๆœ‰ไธไปฅไธ‹ๅˆ’็บฟ๏ผˆ_๏ผ‰ๅผ€ๅคด็š„ๅ็งฐ

ๅคงๅคšๆ•ฐๆƒ…ๅ†ตไธ‹๏ผŒไธ่ฆ็”จ่ฟ™ไธชๅŠŸ่ƒฝ๏ผŒ่ฟ™็งๆ–นๅผๅ‘่งฃ้‡Šๅ™จๅฏผๅ…ฅไบ†ไธ€ๆ‰นๆœช็Ÿฅ็š„ๅ็งฐ๏ผŒๅฏ่ƒฝไผš่ฆ†็›–ๅทฒ็ปๅฎšไน‰็š„ๅ็งฐใ€‚

  1. ๅ…ณไบŽๅฏผๅ…ฅๆ—ถๅ‘็”Ÿ็š„ไบ‹ๆƒ…๏ผš
  • ๅฝ“ไธ€ไธชๅไธบ spam ็š„ๆจกๅ—่ขซๅฏผๅ…ฅๆ—ถ๏ผŒ่งฃ้‡Šๅ™จ้ฆ–ๅ…ˆๆœ็ดขๅ…ทๆœ‰่ฏฅๅ็งฐ็š„ๅ†…็ฝฎๆจกๅ—ใ€‚
  • ่ฟ™ไบ›ๆจกๅ—็š„ๅๅญ—่ขซๅˆ—ๅœจ sys.buildin_module_names ไธญใ€‚
  • ๅฆ‚ๆžœๆฒกๆœ‰ๆ‰พๅˆฐ๏ผŒๅฎƒๅฐฑๅœจๅ˜้‡ sys.path ็ป™ๅ‡บ็š„็›ฎๅฝ•ๅˆ—่กจไธญๆœ็ดขไธ€ไธชๅไธบ spam.py ็š„ๆ–‡ไปถใ€‚
  1. sys.path ไปŽ่ฟ™ไบ›ไฝ็ฝฎๅˆๅง‹ๅŒ–:
  • ่พ“ๅ…ฅ่„šๆœฌ็š„็›ฎๅฝ•๏ผˆๆˆ–ๆœชๆŒ‡ๅฎšๆ–‡ไปถๆ—ถ็š„ๅฝ“ๅ‰็›ฎๅฝ•๏ผ‰ใ€‚
  • PYTHONPATH ๏ผˆ็›ฎๅฝ•ๅˆ—่กจ๏ผŒไธŽ shell ๅ˜้‡ PATH ็š„่ฏญๆณ•ไธ€ๆ ท๏ผ‰ใ€‚
  • ไพ่ต–ไบŽๅฎ‰่ฃ…็š„้ป˜่ฎคๅ€ผ๏ผˆๆŒ‰็…งๆƒฏไพ‹ๅŒ…ๆ‹ฌไธ€ไธช site-packages ็›ฎๅฝ•๏ผŒ็”ฑ site ๆจกๅ—ๅค„็†๏ผ‰ใ€‚
  1. ๅ…ณไบŽ'็ผ–่ฏ‘'ๆ–‡ไปถๅค„็†๏ผš 6. ๆจกๅ— โ€” Python 3.10.5 ๆ–‡ๆกฃ
  2. ๆ‰พไธๅˆฐๆจกๅ—ๆ—ถ็š„ๅค„็†ๆญฅ้ชค๏ผš
  • ไฝฟ็”จdir()ๅ‡ฝๆ•ฐ็กฎ่ฎคๆœ็ดข่ทฏๅพ„
  • ๅฆ‚ๆžœๆฒกๆ‰พๅˆฐ๏ผŒไฝฟ็”จsys.pathๅฐ†ๅฏนๅบ”่ทฏๅพ„ๅŠ ๅ…ฅ

dir()ๅ‡ฝๆ•ฐๅˆ—ๅ‡บไผšๆ‰€ๆœ‰็ฑปๅž‹็š„ๅ็งฐ๏ผšๅ˜้‡ใ€ๆจกๅ—ใ€ๅ‡ฝๆ•ฐ็ญ‰ใ€‚ไฝ†ไธไผšๅˆ—ๅ‡บๅ†…็ฝฎๅ‡ฝๆ•ฐๅ’Œๅ˜้‡็š„ๅ็งฐใ€‚่ฟ™ไบ›ๅ†…ๅฎน็š„ๅฎšไน‰ๅœจๆ ‡ๅ‡†ๆจกๅ— builtins ้‡Œ

  1. ๅŒ…ๆ˜ฏๆจกๅ—็š„้›†ๅˆ๏ผŒๅญ˜ๅœจๅฝขๅผๆ˜ฏ็›ฎๅฝ•ใ€‚ๅฏผๅ…ฅๅŒ…ๆ—ถ๏ผŒPython ๆœ็ดข sys.path ้‡Œ็š„็›ฎๅฝ•๏ผŒๆŸฅๆ‰พๅŒ…็š„ๅญ็›ฎๅฝ•ใ€‚
  2. ๅŒ…็š„ๆ ‡ๅฟ—: ๅฟ…้กปๆœ‰__path__ๅฑžๆ€ง๏ผŒๅŒ…ๅซ__init__.py
  3. ๅŒ…็š„ๅˆ†็ฑป๏ผš
  • ไผ ็ปŸๅŒ…(regular package): ๅŒ…ๅซไธ€ไธช__init__.py

ๅฏผๅ…ฅๅŒ…็š„ๆ—ถๅ€™๏ผŒๆˆ–้ป˜่ฎคๆ‰ง่กŒ__init__.py้‡Œ้ข็š„ไปฃ็ 

  • ๅ‘ฝๅ็ฉบ้—ดๅŒ…(namespace package): ไธ€็งไป…่ขซ็”จไฝœๅญๅŒ…็š„ๅฎนๅ™จ็š„ package๏ผŒๅ‘ฝๅ็ฉบ้—ดๅŒ…ๅฏไปฅๆฒกๆœ‰ๅฎžไฝ“่กจ็คบ็‰ฉ, ๆฒกๆœ‰__init__.py
  1. ไปŽๅŒ…ๅฏผๅ…ฅ*
  • ๅœจๆ–‡ไปถ็ณป็ปŸๆŸฅๆ‰พๅนถๅฏผๅ…ฅๅŒ…็š„ๆ‰€ๆœ‰ๅญๆจกๅ—ใ€‚่ฟ™้กนๆ“ไฝœ่Šฑ่ดน็š„ๆ—ถ้—ด่พƒ้•ฟ๏ผŒๅนถไธ”ๅฏผๅ…ฅๅญๆจกๅ—ๅฏ่ƒฝไผšไบง็”Ÿไธๅฟ…่ฆ็š„ๅ‰ฏไฝœ็”จ๏ผŒ่ฟ™็งๅ‰ฏไฝœ็”จๅชๆœ‰ๅœจๆ˜พๅผๅฏผๅ…ฅๅญๆจกๅ—ๆ—ถๆ‰ไผšๅ‘็”Ÿใ€‚
  • ๅฏไปฅๅœจ__init__.py้‡Œ้ขไฝฟ็”จ__all__ๅฎšไน‰้ป˜่ฎคๅฏไปฅ่ขซๅฏผๅ…ฅ็š„ๆจกๅ—
  1. ๅŒ…็š„__path__ๅฑžๆ€ง๏ผšๅœจๅฏผๅ…ฅๅŒ…็š„ๆ—ถๅ€™๏ผŒๆ‰ง่กŒ__init__.pyไน‹ๅ‰๏ผŒไผš้ป˜่ฎคๅฐ†่ฟ™ไธชๅฑžๆ€ง่ฟ›่กŒๅˆๅง‹ๅŒ–ใ€‚ไธป่ฆๆ˜ฏๅฐ†ๅฝ“ๅ‰ๅฏผๅ…ฅๅŒ…็š„็›ฎๅฝ•ๆ”พๅ…ฅๆœ็ดข่ทฏๅพ„้‡Œ้ข

5. ๅฏผๅ…ฅ็ณป็ปŸ โ€” Python 3.10.5 ๆ–‡ๆกฃ

่ฐƒ็”จๅฏผๅ…ฅๆœบๅˆถ็š„ๆ–นๅผ

  1. import่ฏญๅฅ/import()
  2. importlib.import_module

importlib่ฏดๆ˜Ž

importlib ๆจกๅ—ๆไพ›ไบ†ไธ€ไธชไธฐๅฏŒ็š„ API ็”จๆฅไธŽๅฏผๅ…ฅ็ณป็ปŸ่ฟ›่กŒไบคไบ’ใ€‚ ไพ‹ๅฆ‚ importlib.import_module() ๆไพ›ไบ†็›ธๆฏ”ๅ†…็ฝฎ็š„ import() ๆ›ดๆŽจ่ใ€ๆ›ด็ฎ€ๅ•็š„ API ็”จๆฅๅ‘่ตท่ฐƒ็”จๅฏผๅ…ฅๆœบๅˆถใ€‚

ๆ›ดๅคš็ป†่Š‚่ฏทๅ‚็œ‹ importlib ๅบ“ๆ–‡ๆกฃ:

importlib --- import ็š„ๅฎž็Žฐ โ€” Python 3.10.5 ๆ–‡ๆกฃ

ๅฏผๅ…ฅๆจกๅ—ๅ‘็”Ÿไบ†ไป€ไนˆ

  1. ๅฝ“ไธ€ไธชๆจกๅ—้ฆ–ๆฌก่ขซๅฏผๅ…ฅๆ—ถ๏ผŒPython ไผšๆœ็ดข่ฏฅๆจกๅ—
  2. ๅฆ‚ๆžœๆ‰พๅˆฐๅฐฑๅˆ›ๅปบไธ€ไธช module ๅฏน่ฑก 1 ๅนถๅˆๅง‹ๅŒ–ๅฎƒใ€‚
  3. ๅฆ‚ๆžœๆŒ‡ๅฎšๅ็งฐ็š„ๆจกๅ—ๆœชๆ‰พๅˆฐ๏ผŒๅˆ™ไผšๅผ•ๅ‘ ModuleNotFoundErrorใ€‚
  4. ๅฝ“ๅ‘่ตท่ฐƒ็”จๅฏผๅ…ฅๆœบๅˆถๆ—ถ๏ผŒPython ไผšๅฎž็Žฐๅคš็ง็ญ–็•ฅๆฅๆœ็ดขๆŒ‡ๅฎšๅ็งฐ็š„ๆจกๅ—ใ€‚

่ฟ™ไบ›็ญ–็•ฅๅฏไปฅ้€š่ฟ‡ไฝฟ็”จไฝฟ็”จไธ‹ๆ–‡ๆ‰€ๆ่ฟฐ็š„ๅคš็ง้’ฉๅญๆฅๅŠ ไปฅไฟฎๆ”นๅ’Œๆ‰ฉๅฑ•ใ€‚

3.3็‰ˆๆ›ดๆ”น

ๅœจ 3.3 ็‰ˆๆ›ดๆ”น: ๅฏผๅ…ฅ็ณป็ปŸๅทฒ่ขซๆ›ดๆ–ฐไปฅๅฎŒๅ…จๅฎž็Žฐ PEP 302 ไธญ็š„็ฌฌไบŒ้˜ถๆฎต่ฆๆฑ‚ใ€‚ ไธไผšๅ†ๆœ‰ไปปไฝ•้šๅผ็š„ๅฏผๅ…ฅๆœบๅˆถ โ€”โ€” ๆ•ดไธชๅฏผๅ…ฅ็ณป็ปŸ้ƒฝ้€š่ฟ‡ sys.meta_path ๆšด้œฒๅ‡บๆฅใ€‚ ๆญคๅค–๏ผŒๅฏนๅŽŸ็”Ÿๅ‘ฝๅ็ฉบ้—ดๅŒ…็š„ๆ”ฏๆŒไนŸๅทฒ่ขซๅฎž็Žฐ (ๅ‚่ง PEP 420)ใ€‚

python็š„ๆจกๅ—

Python ๅชๆœ‰ไธ€็งๆจกๅ—ๅฏน่ฑก็ฑปๅž‹๏ผŒๆ‰€ๆœ‰ๆจกๅ—้ƒฝๅฑžไบŽ่ฏฅ็ฑปๅž‹๏ผŒๆ— ่ฎบๆจกๅ—ๆ˜ฏ็”จ Pythonใ€C ่ฟ˜ๆ˜ฏๅˆซ็š„่ฏญ่จ€ๅฎž็Žฐใ€‚

python็š„ๅŒ…

ไธบไบ†ๅธฎๅŠฉ็ป„็ป‡ๆจกๅ—ๅนถๆไพ›ๅ็งฐๅฑ‚ๆฌก็ป“ๆž„๏ผŒPython ่ฟ˜ๅผ•ๅ…ฅไบ† ๅŒ… ็š„ๆฆ‚ๅฟตใ€‚

ไฝ ๅฏไปฅๆŠŠๅŒ…็œ‹ๆˆๆ˜ฏๆ–‡ไปถ็ณป็ปŸไธญ็š„็›ฎๅฝ•๏ผŒๅนถๆŠŠๆจกๅ—็œ‹ๆˆๆ˜ฏ็›ฎๅฝ•ไธญ็š„ๆ–‡ไปถ

ไฝ†่ฏทไธ่ฆๅฏน่ฟ™ไธช็ฑปๆฏ”ๅš่ฟ‡ไบŽๅญ—้ข็š„็†่งฃ

ๅ› ไธบๅŒ…ๅ’Œๆจกๅ—ไธๆ˜ฏๅฟ…้กปๆฅ่‡ชไบŽๆ–‡ไปถ็ณป็ปŸใ€‚ ไธบไบ†ๆ–นไพฟ็†่งฃๆœฌๆ–‡ๆกฃ๏ผŒๆˆ‘ไปฌๅฐ†็ปง็ปญไฝฟ็”จ่ฟ™็ง็›ฎๅฝ•ๅ’Œๆ–‡ไปถ็š„็ฑปๆฏ”ใ€‚ ไธŽๆ–‡ไปถ็ณป็ปŸไธ€ๆ ท๏ผŒๅŒ…้€š่ฟ‡ๅฑ‚ๆฌก็ป“ๆž„่ฟ›่กŒ็ป„็ป‡๏ผŒๅœจๅŒ…ไน‹ๅ†…้™คไบ†ไธ€่ˆฌ็š„ๆจกๅ—๏ผŒ่ฟ˜ๅฏไปฅๆœ‰ๅญๅŒ…ใ€‚

ๅฏนๆฏ”่”็ณปๅŒ…ๅ’Œๆจกๅ—

ๅŒ…ๅชๆ˜ฏ็‰นๆฎŠ็š„ๆจกๅ—๏ผŒๅ…ทๆœ‰__path__ๅฑžๆ€ง

่ฆๆณจๆ„็š„ไธ€ไธช้‡็‚นๆฆ‚ๅฟตๆ˜ฏๆ‰€ๆœ‰ๅŒ…้ƒฝๆ˜ฏๆจกๅ—๏ผŒไฝ†ๅนถ้žๆ‰€ๆœ‰ๆจกๅ—้ƒฝๆ˜ฏๅŒ…ใ€‚ ๆˆ–่€…ๆขๅฅ่ฏ่ฏด๏ผŒๅŒ…ๅชๆ˜ฏไธ€็ง็‰นๆฎŠ็š„ๆจกๅ—ใ€‚ ็‰นๅˆซๅœฐ๏ผŒไปปไฝ•ๅ…ทๆœ‰ path ๅฑžๆ€ง็š„ๆจกๅ—้ƒฝไผš่ขซๅฝ“ไฝœๆ˜ฏๅŒ…ใ€‚

ๆ‰€ๆœ‰ๆจกๅ—้ƒฝๆœ‰่‡ชๅทฑ็š„ๅๅญ—ใ€‚ ๅญๅŒ…ๅไธŽๅ…ถ็ˆถๅŒ…ๅไผšไปฅ็‚นๅทๅˆ†้š”๏ผŒไธŽ Python ็š„ๆ ‡ๅ‡†ๅฑžๆ€ง่ฎฟ้—ฎ่ฏญๆณ•ไธ€่‡ดใ€‚

ๅŒ…็š„ๅˆ†็ฑป

ๅธธ่ง„ๅŒ…

  1. ๅŒ…ๅซ__init__.pyๆ–‡ไปถ๏ผŒไผšๅœจๅฏผๅ…ฅๆ—ถ้šๅผๆ‰ง่กŒ
  2. ๅฆ‚ๆžœๆฒกๆœ‰__init__.py, ไธ€ไธชๅŒ…ๅซๆ–‡ไปถ็š„็›ฎๅฝ•ไนŸๆ˜ฏไผš่ขซ่ฎคไธบๆ˜ฏไธ€ไธชๅŒ…, ๅ‘ฝๅ็ฉบ้—ดๅŒ…

ๅคšๅฑ‚__init__.py็š„ๆ‰ง่กŒ้กบๅบ

parent/
    __init__.py
    one/
        __init__.py
    two/
        __init__.py
    three/
        __init__.py
import parent.one
  1. ๅฏผๅ…ฅ parent.one ๅฐ†้šๅผๅœฐๆ‰ง่กŒ parent/init.py ๅ’Œ parent/one/init.pyใ€‚
  2. ๅŽ็ปญๅฏผๅ…ฅ parent.two ๆˆ– parent.three ๅˆ™ๅฐ†ๅˆ†ๅˆซๆ‰ง่กŒ parent/two/init.py ๅ’Œ parent/three/init.pyใ€‚

ๅ‘ฝๅ็ฉบ้—ดๅŒ…

  1. ๅ‘ฝๅ็ฉบ้—ดๅŒ…ไธๅŒ…ๅซ__init__.py, ่ฟ™ๆ ทๅฐฑไธไผš้™ๅฎšๆ˜ฏๅ•ไธชๅŒ…ๅ†…็š„ๆจกๅ—ๅ็งฐ
  2. ไธๅŒ…ๅซ__init__.py็š„ๆ—ถๅ€™๏ผŒไธๅŒ็›ฎๅฝ•ไธ‹็š„ๅŒๅๅŒ…ไผš่ขซ่ฎคไธบๆ˜ฏๅŒไธ€ไธชๅŒ…ใ€‚

่ฟ™ไธ€็‚นๅฏไปฅๅ’Œgolang็š„ๅŒ…ๆœบๅˆถๅฏนๆฏ”่”็ณป่ตทๆฅ

ๅ‘ฝๅๅŒ…็š„ๅ‘ฝๅ็ฉบ้—ด, ไธคไธชไธๅŒ็š„ๅŒ…็›ฎๅฝ•่ขซๅˆๅนถๅˆฐไธ€่ตท๏ผŒไฝ ๅฏไปฅๅฏผๅ…ฅspam.blahๅ’Œspam.grok๏ผŒๅนถไธ”ๅฎƒไปฌ่ƒฝๅคŸๅทฅไฝœใ€‚

foo-package/
    spam/
        blah.py

bar-package/
    spam/
        grok.py
>>> import sys
>>> sys.path.extend(['foo-package', 'bar-package'])
>>> import spam.blah
>>> import spam.grok
>>>

ๆœ็ดข

ๅŠ ่ฝฝ

็›ธๅฏนๅฏผๅ…ฅ

ไธพไพ‹็›ธๅฏนๅฏผๅ…ฅ

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py
  • ไฝฟ็”จ"."็›ธๅฏนๅฏผๅ…ฅ
from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
  • ่ฟ˜ๅฏไปฅไธปๅŠจๆทปๅŠ ๆœ็ดข่ทฏๅพ„ๅŽๅฏผๅ…ฅ
# moduleX.py
import sys
sys.append('..')
from moduleA import *

ไปปๅŠกๆŠฝ่ฑก

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅนถๅ‘

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ไปŽIOๆจกๅž‹ๅผ€ๅง‹

1. ๅŒๆญฅ/ๅผ‚ๆญฅใ€้˜ปๅกž/้ž้˜ปๅกžๆฆ‚ๅฟตๅŒบๅˆซ

ๅŒๆญฅๅ’Œๅผ‚ๆญฅ๏ผŒๅ…ณๆณจ็š„ๆ˜ฏๆถˆๆฏ้€šไฟกๆœบๅˆถใ€‚๏ผˆ่ฐƒ็”จ่€…่ง†่ง’๏ผ‰

  • ๅŒๆญฅ๏ผŒๅ‘ๅ‡บไธ€ไธช่ฐƒ็”จ๏ผŒๅœจๆฒกๆœ‰ๅพ—ๅˆฐ็ป“ๆžœไน‹ๅ‰ไธ่ฟ”ๅ›žใ€‚
  • ๅผ‚ๆญฅ๏ผŒๅ‘ๅ‡บไธ€ไธช่ฐƒ็”จ๏ผŒๅœจๆฒกๆœ‰ๅพ—ๅˆฐ็ป“ๆžœไน‹ๅ‰่ฟ”ๅ›žใ€‚

้˜ปๅกžๅ’Œ้ž้˜ปๅกž๏ผŒๅ…ณๆณจ็š„ๆ˜ฏ็จ‹ๅบ็ญ‰ๅพ…่ฐƒ็”จ็ป“ๆžœ็š„็Šถๆ€ใ€‚๏ผˆ่ขซ่ฐƒ็”จ่€…่ง†่ง’๏ผ‰

  • ้˜ปๅกž๏ผŒๅœจ่ฐƒ็”จ็ป“ๆžœ่ฟ”ๅ›žไน‹ๅ‰๏ผŒ็บฟ็จ‹่ขซๆŒ‚่ตทใ€‚
  • ้ž้˜ปๅกž๏ผŒๅœจ่ฐƒ็”จ็ป“ๆžœ่ฟ”ๅ›žไน‹ๅ‰๏ผŒ็บฟ็จ‹ไธไผš่ขซๆŒ‚่ตทใ€‚

้˜ปๅกž๏ผŒไธŽ็ณป็ปŸ่ฐƒ็”จๆœ‰ๅ…ณใ€‚

2. ๅŒๆญฅ/ๅผ‚ๆญฅIO ๆจกๅž‹ๅˆ†็ฑป

                                 +-+ ้˜ป ๅกž I/O (BIO)
                                 |
                                 +-+ ้ž ้˜ป ๅกž I/O (NIO)
                                 |
              +----+ ๅŒ ๆญฅ I/O +--+
              |                  |
              |                  +-+ I/O ๅคš ่ทฏ ๅค ็”จ
              |                  |
              |                  +-+ ไฟก ๅท ้ฉฑ ๅŠจ I/O
I/O ๆจก ๅž‹  +---+
              |
              |
              |                  +-+ Linux (AIO)
              |                  |         (io_uring)
              +----+ ๅผ‚ ๆญฅ I/O +--+
                                 |
                                 +-+ windows (IOCP)

3. ๅŒๆญฅ้˜ปๅกžI/O (blocking I/O)

Application               kernel
+---------+            +-----------+  +---+
|         |   syscall  | no        |      |
|   Read  | +--------> | datagram  |      |
| recvfrom|            | ready     |      |
|         |            |    +      |      +-+ wait for
|         |            |    |      |      +-+ data
|         |            |    v      |      |
|         |            | datagram  |      |
|         |            | ready     |  +---+
|         |            |           |
|         |            | copy      |  +---+
|         |            | datagram  |      |
|process  |            |    +      |      +-+ copy data
|datagram |   return   |    |      |      +-+ from kernel to user
|         | <--------+ |    v      |      |
|         |            |  copy     |  +---+
|         |            |  complete |
+---------+            +-----------+

่พ“ๅ…ฅๆ“ไฝœไธคไธช้˜ถๆฎต๏ผš

  1. ่ฟ›็จ‹็ญ‰ๅพ…ๅ†…ๆ ธๆŠŠๆ•ฐๆฎๅ‡†ๅค‡ๅฅฝ๏ผ›่ฟ™ไธช้˜ถๆฎตๅฏไปฅ้˜ปๅกžไนŸๅฏ้ž้˜ปๅกž๏ผŒ่ฎพ็ฝฎsocketๅฑžๆ€งใ€‚
    • ้˜ปๅกž๏ผš recvfrom ้˜ปๅกž็บฟ็จ‹็›ดๅˆฐ่ฟ”ๅ›žๆ•ฐๆฎๅฐฑ็ปช็š„็ป“ๆžœใ€‚
    • ้ž้˜ปๅกž๏ผš็ซ‹ๅณ่ฟ”ๅ›žไธ€ไธช้”™่ฏฏ๏ผŒ่ฝฎ่ฏข็›ดๅˆฐๆ•ฐๆฎๅฐฑ็ปชใ€‚
  2. ไปŽๅ†…ๆ ธ็ผ“ๅ†ฒๅŒบๅ‘่ฟ›็จ‹็ผ“ๅ†ฒๅŒบๅคๅˆถๆ•ฐๆฎใ€‚๏ผˆไธ€็›ด้˜ปๅกž๏ผ‰

ๅผ‚ๆญฅI/O๏ผŒrecvfromๆ€ปๆ˜ฏ็ซ‹ๅณ่ฟ”ๅ›ž๏ผŒไธคไธช้˜ถๆฎต้ƒฝ็”ฑๅ†…ๆ ธๅฎŒๆˆใ€‚

4. I/O ๅคš่ทฏๅค็”จ๏ผˆI/O Multiplexing )

IOๅคš่ทฏๅค็”จๆ˜ฏไธ€็งๅŒๆญฅIOๆจกๅž‹๏ผŒๅฎž็Žฐไธ€ไธช็บฟ็จ‹ๅฏไปฅ็›‘่ง†ๅคšไธชๆ–‡ไปถๅฅๆŸ„ใ€‚

ๆ”ฏๆŒI/Oๅคš่ทฏๅค็”จ็š„็ณป็ปŸ่ฐƒ็”จๆœ‰ select/pselect/poll/epoll๏ผŒๆœฌ่ดจ้ƒฝๆ˜ฏๅŒๆญฅI/O๏ผŒๅ› ไธบๆ•ฐๆฎๆ‹ท่ด้ƒฝๆ˜ฏ้˜ปๅกž็š„ใ€‚ ้€š่ฟ‡ select/epoll ๆฅๅˆคๆ–ญๆ•ฐๆฎๆŠฅๆ˜ฏๅฆๅ‡†ๅค‡ๅฅฝ๏ผŒๅณๅˆคๆ–ญๅฏ่ฏปๅฏๅ†™็Šถๆ€ใ€‚

5. epoll: ๅŒๆญฅ้˜ปๅกž/้ž้˜ปๅกžๆจกๅž‹

                        +--------------------------------+     +-------------------------+
                        | epoll_ctl                      |     | epoll_wait              |
                        |                                |     |                         |
                        |                                |     |         +----+          |
                        |                 +---+          |     |         |    |          |
                        |                 |   |          |     |         |    |          |
                        |               +-+---+--+       |     |         +--+-+          |
                        |               |        |       |     |            |            |
                        |            +--++     +-++      |     |            |            |
epoll_create  +---->    |            |   |     |  |      |     |         +--+-+          |
                        |            +-+-+     +--+      +---->+         |    |          |
                        |              |                 |event|         |    |          |
                        |         +----+--+              |     |         +--+-+          |
                        |         |       |              |     |            |            |
                        |         ++      |              |     |            |            |
                        |        +--+   +-+-+            |     |         +--+-+          |
                        |        |  |   |   |            |     |         |    |          |
                        |        +--+   +---+            |     |         |    |          |
                        |                                |     |         +----+          |
                        |                    ็บข ้ป‘ ๆ ‘     |     |                 ้“พ ่กจ    |
                        +--------------------------------+     +-------------------------+


epollไธ‰ไธชๅ‡ฝๆ•ฐ

  • epoll_create(int size) : ๅ†…ๆ ธไบง็”Ÿไธ€ไธชepollๅฎžไพ‹ๆ•ฐๆฎ็ป“ๆž„๏ผŒๅนถ่ฟ”ๅ›žไธ€ไธชepfd
  • epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)๏ผšๅฐ†่ขซ็›‘ๅฌ็š„ๆ่ฟฐ็ฌฆๆทปๅŠ ๅˆฐ็บข้ป‘ๆ ‘ๆˆ–ไปŽ็บข้ป‘ๆ ‘ไธญๅˆ ้™คๆˆ–่€…ๅฏน็›‘ๅฌไบ‹ไปถ่ฟ›่กŒไฟฎๆ”นใ€‚
  • epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout): ้˜ปๅกž็ญ‰ๅพ…ๆณจๅ†Œ็š„ไบ‹ไปถๅ‘็”Ÿ๏ผŒ่ฟ”ๅ›žไบ‹ไปถ็š„ๆ•ฐ็›ฎ๏ผŒๅนถๅฐ†่งฆๅ‘็š„ไบ‹ไปถๅ†™ๅ…ฅeventsๆ•ฐ็ป„ไธญ

epoll ไธค็ง่งฆๅ‘ๆœบๅˆถ๏ผš

  • ๆฐดๅนณ่งฆๅ‘ๆœบๅˆถ๏ผˆLT)ใ€‚็ผ“ๅ†ฒๅŒบๅช่ฆๆœ‰ๆ•ฐๆฎๅฐฑ่งฆๅ‘่ฏปๅ†™ใ€‚epoll ้ป˜่ฎคๅทฅไฝœๆ–นๅผใ€‚select/pollๅชๆ”ฏๆŒ่ฏฅๆ–นๅผใ€‚
  • ่พน็ผ˜่งฆๅ‘ๆœบๅˆถ๏ผˆET)ใ€‚็ผ“ๅ†ฒๅŒบ็ฉบๆˆ–ๆปก็š„็Šถๆ€ๆ‰่งฆๅ‘่ฏปๅ†™ใ€‚nginx ไฝฟ็”จ่ฏฅๆ–นๅผ๏ผŒ้ฟๅ…้ข‘็น่ฏปๅ†™ใ€‚

ๆƒŠ็พค้—ฎ้ข˜๏ผš

ๅฝ“ๅคšไธช่ฟ›็จ‹/็บฟ็จ‹่ฐƒ็”จepoll_waitๆ—ถไผš้˜ปๅกž็ญ‰ๅพ…๏ผŒๅฝ“ๅ†…ๆ ธ่งฆๅ‘ๅฏ่ฏปๅ†™ไบ‹ไปถ๏ผŒๆ‰€ๆœ‰่ฟ›็จ‹/็บฟ็จ‹้ƒฝไผš่ฟ›่กŒๅ“ๅบ”๏ผŒไฝ†ๆ˜ฏๅฎž้™…ไธŠๅชๆœ‰ไธ€ไธช่ฟ›็จ‹/็บฟ็จ‹็œŸๅฎžๅค„็†่ฟ™ไบ›ไบ‹ไปถใ€‚ Liux 4.5 ้€š่ฟ‡ๅผ•ๅ…ฅ EPOLLEXCLUSIVE ๆ ‡่ฏ†ๆฅไฟ่ฏไธ€ไธชไบ‹ไปถๅ‘็”Ÿๆ—ถๅ€™ๅชๆœ‰ไธ€ไธช็บฟ็จ‹ไผš่ขซๅ”ค้†’๏ผŒไปฅ้ฟๅ…ๅคšไพฆๅฌไธ‹็š„ๆƒŠ็พค้—ฎ้ข˜ใ€‚

6. ๅผ‚ๆญฅ I/O ๆจกๅž‹: io_uring

Linux AIO ๅฎž็Žฐ็š„ๅนถไธ็†ๆƒณ๏ผŒๆ‰€ไปฅๅผ•ๅ…ฅไบ†ๆ–ฐ็š„ๅผ‚ๆญฅI/OๆŽฅๅฃ io_uringใ€‚

+----+ Head  +---------+               +----------+ Head
|            |         |               |          |
|            |         |               |          |
|            +---------+               +----------+
|            |         |               |          |
|            |         |               |          |
|            +---------+               +----------+
|            |         |               |          |
|            |         |               |          |
|            +---------+               +----------+
|            |         |               |          |
|      Tail  +---------+               +----------+ Tail <--+
|        +--------------------------------------------+     |
|        | Kernel                                     |     |
|        |                                            |     |
|        |        +-------+              +-------+    |     |
|        |        |       |              |       |    |     |
+---------------> | SQ    |              |  CQ   | +--------+
         |        |       |              |       |    |
         |        +-------+              +-------+    |
         |                                            |
         +--------------------------------------------+

io_uringๆŽฅๅฃ้€š่ฟ‡ไธคไธชไธป่ฆๆ•ฐๆฎ็ป“ๆž„ๅทฅไฝœ๏ผš

  • ๆไบค้˜Ÿๅˆ—ๆก็›ฎ๏ผˆsqe๏ผ‰
  • ๅฎŒๆˆ้˜Ÿๅˆ—ๆก็›ฎ๏ผˆcqe๏ผ‰

่ฟ™ไบ›็ป“ๆž„็š„ๅฎžไพ‹ไฝไบŽๅ†…ๆ ธๅ’Œๅบ”็”จ็จ‹ๅบไน‹้—ด็š„ๅ…ฑไบซๅ†…ๅญ˜ๅ•็”Ÿไบง่€…ๅ•ๆถˆ่ดน่€…็Žฏๅฝข็ผ“ๅ†ฒๅŒบไธญใ€‚

ๅ‚่€ƒ๏ผš

https://thenewstack.io/how-io_uring-and-ebpf-will-revolutionize-programming-in-linux/

https://cor3ntin.github.io/posts/iouring/#io_uring

ๅ› ไธบๅค„็† I/O ๅค็”จ็š„็ผ–็จ‹ๆจกๅž‹็›ธๅฝ“ๅคๆ‚๏ผŒไธบไบ†็ฎ€ๅŒ–็ผ–็จ‹๏ผŒๅผ•ๅ…ฅไบ†ไธ‹้ขไธค็งๆจกๅž‹:

1. Reactor๏ผˆๅๅบ”ๅ™จ๏ผ‰ ๆจกๅผ

ๅฏนๅบ”ๅŒๆญฅI/O๏ผŒ่ขซๅŠจ็š„ไบ‹ไปถๅˆ†็ฆปๅ’Œๅˆ†ๅ‘ๆจกๅž‹ใ€‚ๆœๅŠก็ญ‰ๅพ…่ฏทๆฑ‚ไบ‹ไปถ็š„ๅˆฐๆฅ๏ผŒๅ†้€š่ฟ‡ไธๅ—้—ดๆ–ญ็š„ๅŒๆญฅๅค„็†ไบ‹ไปถ๏ผŒไปŽ่€Œๅšๅ‡บๅๅบ”ใ€‚

2. Preactor๏ผˆไธปๅŠจๅ™จ๏ผ‰ ๆจกๅผ

ๅฏนๅบ”ๅผ‚ๆญฅI/O๏ผŒไธปๅŠจ็š„ไบ‹ไปถๅˆ†็ฆปๅ’Œๅˆ†ๅ‘ๆจกๅž‹ใ€‚่ฟ™็ง่ฎพ่ฎกๅ…่ฎธๅคšไธชไปปๅŠกๅนถๅ‘็š„ๆ‰ง่กŒ๏ผŒไปŽ่€Œๆ้ซ˜ๅžๅ้‡๏ผ›ๅนถๅฏๆ‰ง่กŒ่€—ๆ—ถ้•ฟ็š„ไปปๅŠก๏ผˆๅ„ไธชไปปๅŠก้—ดไบ’ไธๅฝฑๅ“๏ผ‰ใ€‚

Reactor Model:

                                                     +----------------+
req                                        Dispatch  |                |
+------+                                  +--------> | req handler    |
|      |                                  |          +----------------+
|      | +----+                           |
+------+      | event    +------------+   |
              |          |            |   |
              +--------> |  Service   |   |Dispatch  +----------------+
                         |  Handler   +------------> |                |
req          +---------> |            |   |          | req handler    |
+------+     |           +------------+   |          +----------------+
|      |     | event                      |
|      +----+                             |
+------+                                  | Dispatch +----------------+
                                          +--------->+                |
                                                     | req handler    |
                                                     +----------------+

ไธ‰็งๅฎž็Žฐๆ–นๅผ๏ผš

  • ๅ•็บฟ็จ‹ๆจกๅผใ€‚ accept()ใ€read()ใ€write()ไปฅๅŠconnect()ๆ“ไฝœ ้ƒฝๅœจๅŒไธ€็บฟ็จ‹ใ€‚
  • ๅทฅไฝœ่€…็บฟ็จ‹ๆฑ ๆจกๅผใ€‚้ž I/O ๆ“ไฝœไบค็ป™็บฟ็จ‹ๆฑ ๅค„็†
  • ๅคš็บฟ็จ‹ๆจกๅผใ€‚ไธปReactor (master) ๏ผŒ่ดŸ่ดฃ็ฝ‘็ปœ็›‘ๅฌ ๏ผŒ ๅญReactor(worker) ่ฏปๅ†™็ฝ‘็ปœๆ•ฐๆฎใ€‚

่ฏปๅ†™ๆ“ไฝœๆต็จ‹๏ผš

  1. ๅบ”็”จๆณจๅ†Œ่ฏปๅ†™ๅฐฑ็ปชไบ‹ไปถๅ’Œ็›ธๅ…ณ่”็š„ไบ‹ไปถๅค„็†ๅ™จ
  2. ไบ‹ไปถๅˆ†็ฆปๅ™จ็ญ‰ๅพ…ไบ‹ไปถๅ‘็”Ÿ
  3. ๅฝ“ๅ‘็”Ÿ่ฏปๅ†™ๅฐฑ็ปชไบ‹ไปถ๏ผŒไบ‹ไปถๅˆ†็ฆปๅ™จ่ฐƒ็”จๅทฒๆณจๅ†Œ็š„ไบ‹ไปถๅค„็†ๅ™จ
  4. ไบ‹ไปถๅค„็†ๅ™จๆ‰ง่กŒ่ฏปๅ†™ๆ“ไฝœ

ๅ‚ไธŽ่€…๏ผš

  1. ๆ่ฟฐ็ฌฆ๏ผˆhandle๏ผ‰๏ผšๆ“ไฝœ็ณป็ปŸๆไพ›็š„่ต„ๆบ๏ผŒ่ฏ†ๅˆซ socket็ญ‰ใ€‚
  2. ๅŒๆญฅไบ‹ไปถๅคš่ทฏๅˆ†็ฆปๅ™จใ€‚ๅผ€ๅฏไบ‹ไปถๅพช็Žฏ๏ผŒ็ญ‰ๅพ…ไบ‹ไปถ็š„ๅ‘็”Ÿใ€‚ๅฐ่ฃ…ไบ† ๅคš่ทฏๅค็”จๅ‡ฝๆ•ฐ select/poll/epoll็ญ‰ใ€‚
  3. ไบ‹ไปถๅค„็†ๅ™จใ€‚ๆไพ›ๅ›ž่ฐƒๅ‡ฝๆ•ฐ๏ผŒ็”จไบŽๆ่ฟฐไธŽๅบ”็”จ็จ‹ๅบ็›ธๅ…ณ็š„ๆŸไธชไบ‹ไปถ็š„ๆ“ไฝœใ€‚
  4. ๅ…ทไฝ“็š„ไบ‹ไปถๅค„็†ๅ™จใ€‚ไบ‹ไปถๅค„็†ๅ™จๆŽฅๅฃ็š„ๅ…ทไฝ“ๅฎž็Žฐใ€‚ไฝฟ็”จๆ่ฟฐ็ฌฆๆฅ่ฏ†ๅˆซไบ‹ไปถๅ’Œ็จ‹ๅบๆไพ›็š„ๆœๅŠกใ€‚
  5. Reactor ็ฎก็†ๅ™จใ€‚ไบ‹ไปถๅค„็†ๅ™จ็š„่ฐƒๅบฆๆ ธๅฟƒใ€‚ๅˆ†็ฆปๆฏไธชไบ‹ไปถ๏ผŒ่ฐƒๅบฆไบ‹ไปถ็ฎก็†ๅ™จ๏ผŒ่ฐƒ็”จๅ…ทไฝ“็š„ๅ‡ฝๆ•ฐๅค„็†ๆŸไธชไบ‹ไปถใ€‚

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅคš็บฟ็จ‹ๅนถๅ‘ๆจกๅž‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅผ‚ๆญฅๆจกๅž‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅ…ƒ็ผ–็จ‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅ่ฎฎๆŠฝ่ฑก

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅคš่ฏญ่จ€็ผ–็จ‹

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

่ฎก็ฎ—ๆœบ็ฝ‘็ปœ

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

็”Ÿๆ€็ณป็ปŸ

ๅ‚่€ƒ่ต„ๆบ

online-book

fragment

local

ๅญฆไน ่ต„ๆบ

ๅฎ˜ๆ–นๅŠจๆ€

็คพๅŒบ็‰น็‚น

ๅญฆๆœฏๅŠจๆ€

ๅผ€ๆบ่ง‚ๅฏŸ

ๅ‘ฝไปค่กŒๅทฅๅ…ท

ๆ•ฐๆฎๅค„็†

ๅตŒๅ…ฅๅผ

ๆ“ไฝœ็ณป็ปŸ

pythontutor้กน็›ฎ่งฃๅ‰–

่ฏดๆ˜Ž

ๆœฌๆ–‡ไธป่ฆๅ‰–ๆžไธ€ไธ‹pythontutor็š„้กน็›ฎ็ป“ๆž„ไธŽไธšๅŠกๆต็จ‹๏ผŒๅนถ็กฎๅฎšๅŽ้ข็š„็›ธๅ…ณไปฃ็ ๅฏ่ง†ๅŒ–็š„ไฝฟ็”จๆ–นๆณ•

ๆ€ปไฝ“็ป“ๆž„ๅ›พ

pythontutor็ป“ๆž„ๅ›พ

                                                                                                                                                  โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“ 
                                                                                                                                                  โ”ƒ                              _                    _                            โ”ƒ 
                                                                                                                                                  โ”ƒ                _ __  __ _ __| |____ _ __ _ ___   (_)___ ___ _ _                โ”ƒ 
                                                                                                                                                  โ”ƒ               | '_ \/ _` / _| / / _` / _` / -_)_ | (_-</ _ \ ' \               โ”ƒ 
                                                                                                                                                  โ”ƒ               | .__/\__,_\__|_\_\__,_\__, \___(_)/ /__/\___/_||_|              โ”ƒ 
โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“                                                               โ”ƒ               |_|                    |___/     |__/                            โ”ƒ 
โ”ƒ       ___      _   _               _____     _             ___                  โ”ƒ                                                               โ”ƒ                                                                                โ”ƒ 
โ”ƒ      | _ \_  _| |_| |_  ___ _ _   |_   _|  _| |_ ___ _ _  | __|_ _____ __       โ”ƒ                                                               โ”ƒ   {                                                                            โ”ƒ 
โ”ƒ      |  _/ || |  _| ' \/ _ \ ' \    | || || |  _/ _ \ '_| | _|\ \ / -_) _|      โ”ƒ                                                               โ”ƒ     "name": "v5-unity",                                                        โ”ƒ 
โ”ƒ      |_|  \_, |\__|_||_\___/_||_|   |_| \_,_|\__\___/_|   |___/_\_\___\__|      โ”ƒ                                                               โ”ƒ     "version": "1.0.0",                                                        โ”ƒ 
โ”ƒ           |__/                                                                  โ”ƒ                                                               โ”ƒ     "description": "OPT v5",                                                   โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "main": "bundle.js",                                                       โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "repository": "https://github.com/pgbovine/OnlinePythonTutor",             โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "license": "BSD-3-Clause",                                                 โ”ƒ 
โ”ƒ                                                                                 โ”ƒ                                                               โ”ƒ     "scripts": {                                                               โ”ƒ 
โ”ƒ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                     โ”ƒ                                                               โ”ƒ       "start": "python bottle_server.py",                                      โ”ƒ 
โ”ƒ  โ”‚                        โ”‚                                                     โ”ƒ                                                               โ”ƒ       "py3start": "python3 bottle_server.py",                                  โ”ƒ 
โ”ƒ  โ”‚    botter_server.py    โ”‚                                                     โ”ƒ                                                     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ซ       "webpack": "webpack --devtool sourcemap --progress --colors --watch",    โ”ƒ 
โ”ƒ  โ”‚      get_py_exec       โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                        โ”ƒ                                                     โ”‚         โ”ƒ       "production-build": "rm -f build/* && webpack && python                  โ”ƒ 
โ”ƒ  โ”‚                        โ”‚            โ”‚                                        โ”ƒ                                                     โ”‚         โ”ƒ   add_cache_busting_query_strings.py"                                          โ”ƒ 
โ”ƒ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚                                        โ”ƒ                                                     โ”‚         โ”ƒ     },                                                                         โ”ƒ 
โ”ƒ                                        โ”‚                                        โ”ƒ                                                     โ”‚         โ”ƒ     "dependencies": {                                                          โ”ƒ 
โ”ƒ                                        โ”‚           โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”ƒ                                                     โ”‚         โ”ƒ       "css-loader": "",                                                        โ”ƒ 
โ”ƒ                                        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ                         โ”‚  โ”ƒ                                   npm run production-build    โ”ƒ       "fs-extra": "^6.0.1",                                                    โ”ƒ 
โ”ƒ                                                    โ”‚      pg_logger.py       โ”‚  โ”ƒ                                                     โ”‚         โ”ƒ       "json-stable-stringify": "^1.0.1",                                       โ”ƒ 
โ”ƒ                                                    โ”‚  exec_script_str_local  โ”‚  โ”ƒ                                                     โ”‚         โ”ƒ       "on-build-webpack": "^0.1.0",                                            โ”ƒ 
โ”ƒ                                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                         โ”‚  โ”ƒ                                                     โ”‚         โ”ƒ       "pixelmatch": "^4.0.2",                                                  โ”ƒ 
โ”ƒ                                        โ”‚           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”ƒ                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”‚         โ”ƒ       "puppeteer": "^1.5.0",                                                   โ”ƒ 
โ”ƒ                                        โ”‚                                        โ”ƒ                  โ”‚                         โ”‚        โ”‚         โ”ƒ       "script-loader": "",                                                     โ”ƒ 
โ”ƒ                                        โ”‚                                        โ”ƒ                  โ”‚     /visualize.html     โ”‚        โ”‚         โ”ƒ       "style-loader": "",                                                      โ”ƒ 
โ”ƒ                                        โ”‚                       โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•‹โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ   visualize.bundle.js   โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”ƒ       "ts-loader": "^3.5.0",                                                   โ”ƒ 
โ”ƒ  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”‚                       โ”‚                โ”ƒ                  โ”‚                         โ”‚                  โ”ƒ       "url-loader": ""                                                         โ”ƒ 
โ”ƒ  โ”‚                         โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜               return trace info        โ”ƒ                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                  โ”ƒ     }                                                                          โ”ƒ 
โ”ƒ  โ”‚      pg_logger.py       โ”‚                         {code: '', trace: []}      โ”ƒ                                                               โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ–ฒโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”› 
โ”ƒ  โ”‚   PGLogger._runscript   โ”‚                                   โ”‚                โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ  โ”‚                         โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                    โ”ƒ                                                                                                   webpack                                        
โ”ƒ                                                                                 โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ                                                                                 โ”ƒ                                                                                                       โ”‚                                          
โ”ƒ                                                                                 โ”ƒ                                                                โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”ปโ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”“
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ                  _                  _                  __ _         _          โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ      __ __ _____| |__ _ __  __ _ __| |__  __ ___ _ _  / _(_)__ _   (_)___      โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ      \ V  V / -_) '_ \ '_ \/ _` / _| / /_/ _/ _ \ ' \|  _| / _` |_ | (_-<      โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ       \_/\_/\___|_.__/ .__/\__,_\__|_\_(_)__\___/_||_|_| |_\__, (_)/ /__/      โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ                      |_|                                   |___/ |__/          โ”ƒ
โ”ƒ                                                                                 โ”ƒ                                                                โ”ƒ   entry: {                                                                     โ”ƒ
โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›                                                                โ”ƒ       'visualize': "./js/visualize.ts",                                        โ”ƒ
                                                                                                                                                   โ”ƒ       'recorder': "./js/recorder.ts",                                          โ”ƒ
                                                                                                                                                   โ”ƒ       'render-trace': "./js/render-trace.ts",                                  โ”ƒ
                                                                                                                                                   โ”ƒ       'opt-live': "./js/opt-live.ts",                                          โ”ƒ
                                                                                                                                                   โ”ƒ       'iframe-embed': "./js/iframe-embed.ts",                                  โ”ƒ
                                                                                                                                                   โ”ƒ       'index': "./js/index.ts",                                                โ”ƒ
                                                                                                                                                   โ”ƒ       'composingprograms': "./js/composingprograms.ts",                        โ”ƒ
                                                                                                                                                   โ”ƒ       'csc108h': "./js/csc108h.ts",                                            โ”ƒ
                                                                                                                                                   โ”ƒ       'pytutor-embed': "./js/pytutor-embed.ts",                                โ”ƒ
                                                                                                                                                   โ”ƒ   },                                                                           โ”ƒ
                                                                                                                                                   โ”ƒ                                                                                โ”ƒ
                                                                                                                                                   โ”ƒ   output: {                                                                    โ”ƒ
                                                                                                                                                   โ”ƒ       path: __dirname + "/build/",                                             โ”ƒ
                                                                                                                                                   โ”ƒ       // TODO: use 'bundle.[hash].js' for fingerprint hashing                  โ”ƒ
                                                                                                                                                   โ”ƒ       // to create unique filenames for releases:                              โ”ƒ
                                                                                                                                                   โ”ƒ       // https://webpack.github.io/docs/long-term-caching.html                 โ”ƒ
                                                                                                                                                   โ”ƒ       filename: "[name].bundle.js",                                            โ”ƒ
                                                                                                                                                   โ”ƒ       sourceMapFilename: "[file].map",                                         โ”ƒ
                                                                                                                                                   โ”ƒ   },                                                                           โ”ƒ
                                                                                                                                                   โ”—โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”›

iframeไฝฟ็”จ็คบไพ‹

ไฝฟ็”จbottleๅ†™webๆœๅŠก

from bottle import route, get, request, run, template, static_file

try:
    import StringIO  # NB: don't use cStringIO since it doesn't support unicode!!!
except:
    import io as StringIO  # py3
import json
import pg_logger


@route('/web_exec_<name:re:.+>.py')
@route('/LIVE_exec_<name:re:.+>.py')
@route('/viz_interaction.py')
@route('/syntax_err_survey.py')
@route('/runtime_err_survey.py')
@route('/eureka_survey.py')
@route('/error_log.py')
def dummy_ok(name=None):
    return 'OK'


@route('/<filepath:path>')
def index(filepath):
    return static_file(filepath, root='.')


# Note that this will run either Python 2 or 3, depending on which
# version of Python you used to start the server, REGARDLESS of which
# route was taken:
@route('/web_exec_py2.py')
@route('/web_exec_py3.py')
@route('/LIVE_exec_py2.py')
@route('/LIVE_exec_py3.py')
def get_py_exec():
    out_s = StringIO.StringIO()

    def json_finalizer(input_code, output_trace):
        ret = dict(code=input_code, trace=output_trace)
        json_output = json.dumps(ret, indent=None)
        out_s.write(json_output)

    options = json.loads(request.query.options_json)

    pg_logger.exec_script_str_local(request.query.user_script,
                                    request.query.raw_input_json,
                                    options['cumulative_mode'],
                                    options['heap_primitives'],
                                    json_finalizer)

    return out_s.getvalue()


if __name__ == "__main__":
    run(host='localhost', port=8003, reloader=True)

่ฟ™้‡Œๅฏไปฅๅ‘็Žฐ๏ผŒไฝœ่€…็š„่ทฏ็”ฑๅŸบๆœฌๆฑ‡่šๅœจget_py_exec, ่ฟ›ๅ…ฅๅŽๆ‰ง่กŒexec_script_str_local

pg_logger.pyไป‹็ป

python tutorๆ ธๅฟƒ็ฑป

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                        
โ”‚                   โ”‚                                                        
โ”‚ botter_server.py  โ”‚                                                        
โ”‚    get_py_exec    โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                         
โ”‚                   โ”‚              โ”‚                                         
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜              โ”‚                                         
                                   โ”‚                                         
                                   โ”‚              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ                         โ”‚
                                                  โ”‚      pg_logger.py       โ”‚
                                                  โ”‚  exec_script_str_local  โ”‚
                                      โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                         โ”‚
                                      โ”‚           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                      โ”‚                                      
                                      โ”‚                                      
                                      โ”‚                                      
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”           โ”‚                                      
โ”‚                         โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                      
โ”‚      pg_logger.py       โ”‚                                                  
โ”‚   PGLogger._runscript   โ”‚                                                  
โ”‚                         โ”‚                                                  
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                  

็ปงๆ‰ฟ่‡ชBdb

class PGLogger(bdb.Bdb):

ๅˆๅง‹ๅŒ–็›ธๅ…ณ

    def __init__(
            self,
            cumulative_mode,
            heap_primitives,
            show_only_outputs,
            finalizer_func,
            disable_security_checks=False,
            allow_all_modules=False,
            crazy_mode=False,
            custom_modules=None,
            separate_stdout_by_module=False,
            probe_exprs=None):

่ฐƒ็”จๅ‡ฝๆ•ฐ

def exec_script_str_local(
        script_str,
        raw_input_lst_json,
        cumulative_mode,
        heap_primitives,
        finalizer_func,
        probe_exprs=None,
        allow_all_modules=False):
    # ๆ ธๅฟƒ่ฟ่กŒ่ฟ‡็จ‹่ฎฐๅฝ•็ฑป
    logger = PGLogger(
        cumulative_mode,
        heap_primitives,
        False,
        finalizer_func,
        disable_security_checks=True,
        allow_all_modules=allow_all_modules,
        probe_exprs=probe_exprs
    )

    # TODO: refactor these NOT to be globals
    global input_string_queue
    input_string_queue = []
    if raw_input_lst_json:
        # TODO: if we want to support unicode, remove str() cast
        input_string_queue = [str(e) for e in json.loads(raw_input_lst_json)]

    try:
        logger._runscript(script_str)
    except bdb.BdbQuit:
        pass
    finally:
        return logger.finalize()

่ฟ”ๅ›žๆ•ฐๆฎ็คบไพ‹

{
  "code": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())",
  "trace": [
    {
      "line": 5,
      "event": "step_line",
      "func_name": "<module>",
      "globals": {},
      "ordered_globals": [],
      "stack_to_render": [],
      "heap": {},
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 19,
      "event": "step_line",
      "func_name": "<module>",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [],
      "heap": {},
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 10,
      "event": "call",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601"
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 11,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601"
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 12,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "name",
            "Pat"
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 13,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 14,
      "event": "step_line",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 14,
      "event": "return",
      "func_name": "__init__",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ]
      },
      "ordered_globals": [
        "Staff601"
      ],
      "stack_to_render": [
        {
          "func_name": "__init__",
          "is_parent": false,
          "frame_id": 1,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "name": "Pat",
            "role": "Professor",
            "years": 60,
            "salary": 100000,
            "__return__": null
          },
          "ordered_varnames": [
            "self",
            "name",
            "role",
            "years",
            "salary",
            "__return__"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "__init___f1"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 20,
      "event": "step_line",
      "func_name": "<module>",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 16,
      "event": "call",
      "func_name": "salutation",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [
        {
          "func_name": "salutation",
          "is_parent": false,
          "frame_id": 2,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ]
          },
          "ordered_varnames": [
            "self"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "salutation_f2"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 17,
      "event": "step_line",
      "func_name": "salutation",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [
        {
          "func_name": "salutation",
          "is_parent": false,
          "frame_id": 2,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ]
          },
          "ordered_varnames": [
            "self"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "salutation_f2"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 17,
      "event": "return",
      "func_name": "salutation",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [
        {
          "func_name": "salutation",
          "is_parent": false,
          "frame_id": 2,
          "parent_frame_id_list": [],
          "encoded_locals": {
            "self": [
              "REF",
              1
            ],
            "__return__": "Professor Pat"
          },
          "ordered_varnames": [
            "self",
            "__return__"
          ],
          "is_zombie": false,
          "is_highlighted": true,
          "unique_hash": "salutation_f2"
        }
      ],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\n"
    },
    {
      "line": 20,
      "event": "return",
      "func_name": "<module>",
      "globals": {
        "Staff601": [
          "IMPORTED_FAUX_PRIMITIVE",
          "imported class"
        ],
        "pat": [
          "REF",
          1
        ]
      },
      "ordered_globals": [
        "Staff601",
        "pat"
      ],
      "stack_to_render": [],
      "heap": {
        "1": [
          "INSTANCE",
          "Staff601",
          [
            "age",
            60
          ],
          [
            "name",
            "Pat"
          ],
          [
            "role",
            "Professor"
          ],
          [
            "salary",
            100000
          ]
        ]
      },
      "stdout": "# The __init__ 'constructor' - object-oriented programming intro\n# Adapted from MIT 6.01 course notes (Section 3.5)\n# http://mit.edu/6.01/mercurial/spring10/www/handouts/readings.pdf\n\nclass Staff601:\n    course = '6.01'\n    building = 34\n    room = 501\n\n    def __init__(self, name, role, years, salary):\n      self.name = name\n      self.role = role\n      self.age = years\n      self.salary = salary\n\n    def salutation(self):\n        return self.role + ' ' + self.name\n\npat = Staff601('Pat', 'Professor', 60, 100000)\nprint(pat.salutation())\nProfessor Pat\n"
    }
  ]
}

ๅ‚่€ƒ่ต„ๆ–™

ๆ€ง่ƒฝๅทฅๅ…ท

ไบ‘ๅŽŸ็”Ÿ

ๅ‰็ซฏๅผ€ๅ‘

็ฝ‘็ปœๅŸบๅปบ

็ฝ‘็ปœๅผ€ๅ‘

้Ÿณ่ง†้ข‘ๅค„็†

ๆธธๆˆไธŽๅ›พๅƒๅค„็†

ๅฎ‰ๅ…จๅ‚่€ƒ

ๅ•†ไธš่ง‚ๅฏŸ

็”Ÿไบงๅฎž่ทต

ไผ˜็ง€ไบงๅ“

awesome series

vinta/awesome-python

ๅŸบ็ก€ๅบ“

ๅ†…็ฝฎๅบ“ไป‹็ป

osๅบ“

็Žฏๅขƒๅ˜้‡่ฎพ็ฝฎๅŠๅฆ™็”จ

ๆœฌๆฅๆ‰“็ฎ—ๅœจๆ‰ง่กŒ็ˆฌ่™ซ่„šๆœฌๆ—ถ้€š่ฟ‡็Žฏๅขƒๅ˜้‡่ฎพ็ฝฎๅˆ‡ๆขๆฅๅŠๆ‰‹ๅŠจ็ป•่ฟ‡ๆ‹–ๅ—็ญ‰้ชŒ่ฏ็ ๆ‰‹ๆฎต๏ผŒไฝ†ๆ˜ฏPythonๅชไผšๅœจ็ฌฌไธ€ๆฌก่ฟ่กŒๆ—ถๆ•่Žท็Žฏๅขƒๅ˜้‡๏ผŒๆ‰€ไปฅไธ็Žฐๅฎžใ€‚

ๅฎ˜ๆ–นๆ–‡ๆกฃๅฏนos.environ็š„ไป‹็ป

ไธ€ไธช mapping ๅฏน่ฑก๏ผŒๅ…ถไธญ้”ฎๅ€ผๆ˜ฏไปฃ่กจ่ฟ›็จ‹็Žฏๅขƒ็š„ๅญ—็ฌฆไธฒใ€‚ ไพ‹ๅฆ‚๏ผŒenviron['HOME'] ๆ˜ฏไฝ ็š„ไธป็›ฎๅฝ•๏ผˆๅœจๆŸไบ›ๅนณๅฐไธŠ๏ผ‰็š„่ทฏๅพ„ๅ๏ผŒ็›ธๅฝ“ไบŽ C ไธญ็š„ getenv("HOME")ใ€‚

่ฟ™ไธชๆ˜ ๅฐ„ๆ˜ฏๅœจ็ฌฌไธ€ๆฌกๅฏผๅ…ฅ os ๆจกๅ—ๆ—ถๆ•่Žท็š„๏ผŒ้€šๅธธไฝœไธบ Python ๅฏๅŠจๆ—ถๅค„็† site.py ็š„ไธ€้ƒจๅˆ†ใ€‚้™คไบ†้€š่ฟ‡็›ดๆŽฅไฟฎๆ”น os.environ ไน‹ๅค–๏ผŒๅœจๆญคไน‹ๅŽๅฏน็Žฏๅขƒๆ‰€ๅš็š„ๆ›ดๆ”นไธไผšๅๆ˜ ๅœจ os.environ ไธญใ€‚

่ฏฅๆ˜ ๅฐ„้™คไบ†ๅฏไปฅ็”จไบŽๆŸฅ่ฏข็Žฏๅขƒๅค–๏ผŒ่ฟ˜่ƒฝ็”จไบŽไฟฎๆ”น็Žฏๅขƒใ€‚ๅฝ“่ฏฅๆ˜ ๅฐ„่ขซไฟฎๆ”นๆ—ถ๏ผŒๅฐ†่‡ชๅŠจ่ฐƒ็”จ putenv()ใ€‚

ๅœจUnix็ณป็ปŸไธŠ๏ผŒ้”ฎๅ’Œๅ€ผไผšไฝฟ็”จ sys.getfilesystemencoding() ๅ’Œ 'surrogateescape' ็š„้”™่ฏฏๅค„็†ใ€‚ๅฆ‚ๆžœไฝ ๆƒณไฝฟ็”จๅ…ถไป–็š„็ผ–็ ๏ผŒไฝฟ็”จ environbใ€‚

ๆณจ่งฃ ็›ดๆŽฅ่ฐƒ็”จ putenv() ๅนถไธไผšๅฝฑๅ“ os.environ ๏ผŒๆ‰€ไปฅๆŽจ่็›ดๆŽฅไฟฎๆ”น os.environ ใ€‚ ๆณจ่งฃ ๅœจๆŸไบ›ๅนณๅฐไธŠ๏ผŒๅŒ…ๆ‹ฌ FreeBSD ๅ’Œ macOS๏ผŒ่ฎพ็ฝฎ environ ๅฏ่ƒฝๅฏผ่‡ดๅ†…ๅญ˜ๆณ„ๆผใ€‚ ่ฏทๅ‚้˜… putenv() ็š„็ณป็ปŸๆ–‡ๆกฃใ€‚


ๅ‚่€ƒ่ต„ๆบ

ๆ—ฅๅฟ—ๅบ“ไป‹็ป

ๅ‚่€ƒ่ต„ๆบ

ๅผ‚ๅธธ่ฟฝ่ธชๅบ“

ๅŸบ็ก€ไพ‹ๅญ

็ป“ๅˆๆ—ฅๅฟ—ไฝฟ็”จ

import traceback
try:
    do_something()
except Exception:
    #traceback.print_exc(file=sys.stdout)
    loggers.info(traceback.format_exc())
## ๅ‚่€ƒ่ต„ๆบ

ๆก†ๆžถๅผ•ๆ“Ž

Checklist