今天來聊聊路徑,這幾天寫 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'; 去引用,這樣會更萬無一失
沒有留言:
張貼留言