我有开发环境和生产用于运行crontab
中使用的各种Python
脚本。
在开发环境中,我通常在脚本目录中的命令行中测试脚本,例如"python myscript.py"
。现在,某些脚本从脚本目录的相同或子目录中加载JSON
文件的配置。因此,在开发人员中,我可以参考这样的文件:
printconf = Config('printing.json')
但是,一旦脚本准备好生产,它就会放入crontab
,crontab
从root
调用脚本,因此打破上述行。
此外,显然,开发和生产在文件系统中的不同位置,所以我什至无法使用绝对路径,因为它们不会相同。
如我如何与python找到脚本目录中所述?我可以使用各种方法来查找文件当前目录。但是,它们的意思是额外的处理,我想知道,如果任何Python
版本可能具有(或可能已经计划过)任何其他内置方法,以说明必须在运行脚本的目录中找到该文件?类似__location__
?
本质上,可以为文件引用(例如导入模块已经做到的)工作。
此外,我尝试通过sitecustomize.py
添加一个全局__location__
变量,但这甚至行不通。
sitecustomize.py:
if '__file__' in globals():
import os
_location_ = os.path.join(os.getcwd(), os.path.dirname(__file__))
但这也不起作用,因为:-__location__
未传递给脚本, - 和__file__
指sitecustomize.py
首先,您的开发环境和生产环境应该没有太大差异。这意味着,为了一致性,您应该为两者使用相同的设置(文件系统,库等)。这样,您的大多数问题就会消失。如果您这样做,那么使用硬编码路径是安全的。
其他选项(这不可避免地涉及一些处理,但不应是交易破坏者):
- 您已经建议使用
os.getcwd()
和__file__
。 - 在运行脚本时使用特定的参数(例如:
$SCRIPT_PATH/myscript.py PROD
),并根据脚本中的此路径选择路径。 - 仅将专用的配置文件用于脚本init,将其放在Dev和prod上的同一位置(我会在
/etc/$PROJECT_NAME
中建议),并使用特定参数运行脚本(如上所述)。
以上所有方法都不会阻止与一致性相关的其他问题,这使我强调您应该考虑使用Docker或Vagrant进行DEV设置(和/或prod,如有可能)。
当我回顾了这个问题时,很明显,我提供了太多错误的上下文,相关的上下文太少。当我测试实际解决方案时,我决定不重写问题,而是将正确的上下文放在答案中。
大多数问题是由于我想确定文件b的路径相对于脚本A,而实际使用文件B使用了系统范围的模块C(从脚本A中调用)完全不同的地方,这样:
#module C (system-wide in /usr.../site-packages
import os
class Config()
...
def load(file_name):
# needs to be relative to calling script's dir, not module's!
real_file_name=os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])),file_name)
...
#script-A.py ( in /var/scripts/projectA )
from C import Config
conf=Config()
conf.load('file-in-projectA-dir.json')
# finds /var/scripts/projectA/file-in-projectA-dir.json
# regardless of cwd
所以这两者都适用于:
cd /
python3 /var/scripts/projectA/script-A.py
#and:
cd /var/scripts/projectA/
python3 script-A.py
#etc
您可以看到,这仅是由于script-a从命令行称为第一个参数而起作用。但是,这是我的主要用例。不确定,什么可以起作用。