今天來聊聊路徑,這幾天寫 python 要執行 cronjob 的時候發現一件有趣的事情,來看程式碼
# -*- coding: utf-8 -*- def file_get_contents(file_path): with open(file_path, 'r') as the_file: return the_file.read().strip() print(file_get_contents('logs/chan.log'))
我們在 logs 目錄下建一個檔案叫 chan.log,裡面只有 hello world 字串,接下來我們在同等目錄下執行程式
/var/www/python/ $ python path.py hello world
我們得到正確的結果,但假設要寫 cronjob 不會這樣下指令,我們會下 /usr/bin/python /var/www/python/path.py
,我們將目錄切換到 /tmp
再來看看結果
/var/www/python/ $ cd /tmp /tmp $ /usr/bin/python /var/www/python/path.py Traceback (most recent call last): File "/var/www/python/path.py", line 9, in <module> print(file_get_contents('logs/chan.log')) File "/var/www/python/path.py", line 5, in file_get_contents with open(file_path, 'r') as the_file: IOError: [Errno 2] No such file or directory: 'logs/chan.log'
我們得到了找不到目錄或檔案的訊息,python 在執行時會因為不同的位置得不到相對路徑的結果,可以說好也可以說不好,引用的路徑本來就該相對嚴格些,不好在有時候一些簡單的東西想偷懶都不行了,來修正程式碼
# -*- coding: utf-8 -*- import os def file_get_contents(file_path): real_path = os.path.join(os.path.dirname(__file__), file_path) with open(real_path, 'r') as the_file: return the_file.read().strip() print(file_get_contents('logs/chan.log'))
再次執行
/tmp $ /usr/bin/python /var/www/python/path.py hello world
得到正確的結果了,讓我們來看看 node.js
const fs = require('fs'); const content = fs.readFileSync('logs/chan.log').toString().trim(); console.log(content);
/var/www/nodejs $ node path.js hello world /var/www/nodejs $ cd /tmp /tmp $ /usr/bin/node /var/www/nodejs/path.js fs.js:646 return binding.open(pathModule._makeLong(path), stringToFlags(flags), mode); ^ Error: ENOENT: no such file or directory, open 'logs/chan.log' at Object.fs.openSync (fs.js:646:18) at Object.fs.readFileSync (fs.js:551:33) at Object.<anonymous> (/var/www/nodejs/path.js:3:20) at Module._compile (module.js:652:30) at Object.Module._extensions..js (module.js:663:10) at Module.load (module.js:565:32) at tryModuleLoad (module.js:505:12) at Function.Module._load (module.js:497:3) at Function.Module.runMain (module.js:693:10) at startup (bootstrap_node.js:188:16)
沒想到 node.js 的認定跟 python 是一樣的呢,來修改程式碼
const fs = require('fs'); const path = require('path'); const fileGetContents = (filePath) => { const realPath = path.join(__dirname, filePath); return fs.readFileSync(realPath).toString().trim(); }; console.log(fileGetContents('logs/chan.log'));
/tmp $ /usr/bin/node /var/www/nodejs/path.js hello world
得到正確的結果了,我們來看看 PHP
<?php echo trim(file_get_contents('logs/chan.log')), PHP_EOL;
/var/www/php $ php path.php hello world
PHP 一行就寫完了,難怪是這個世界上最好的語言(lol)
/tmp $ /usr/bin/php /var/www/php/path.php PHP Warning: file_get_contents(logs/chan.log): failed to open stream: No such file or directory in /var/www/php/path.php on line 3
OK,事實上只要離開了相對位置,三個語言遇到的情況是一樣的,來修改程式碼
<?php echo trim(file_get_contents(__DIR__.'/logs/chan.log')), PHP_EOL;
/tmp $ /usr/bin/php /var/www/php/path.php hello world
什麼,PHP 加一個 __DIR__
就搞定了,你還在跟我爭 PHP 是不是世界上最好的語言 (lol)?
來總結一下,其實在這三個語言裡用類似 include
語法內部引入檔案時是不會有問題的,例如說 include ../file.php;
,只是我自己習慣還是會 include __DIR__.'/../file.php';
去引用,這樣會更萬無一失
沒有留言:
張貼留言