我有开发环境和生产版本,可以运行Python
中使用的各种crontab
脚本。
在开发环境中,我通常从脚本目录(例如"python myscript.py"
)中的命令行测试脚本。
现在,某些脚本从脚本目录的相同或子目录中的JSON
个文件加载配置。
因此,在开发人员中,我可以这样引用文件:
printconf = Config('printing.json')
但是,一旦脚本准备好用于生产,就将其放入crontab
中,并且crontab
从root
调用脚本,因此破坏了上面的行。
另外,dev和production显然位于文件系统中的不同位置,所以我什至不能使用绝对路径,因为它们不会相同。
如How can I find script's directory with Python?中所述,我可以使用各种方法来查找文件的当前目录。但是,它们的意思是额外的处理,我想知道,
是否有任何Python
版本具有(或可能已经计划)任何其他内置方式来告知必须相对于运行脚本的目录找到文件?像__location__
一样?
从本质上讲,已经可以对文件引用进行操作,例如导入模块。
此外,我尝试通过__location__
添加全局sitecustomize.py
变量,但这什至不起作用。
sitecustomize.py:
if '__file__' in globals():
import os
_location_ = os.path.join(os.getcwd(), os.path.dirname(__file__))
但这也不起作用,因为:
-__location__
没有传递给脚本,
-并且__file__
指的是sitecustomize.py
答案 0 :(得分:0)
首先,您的Dev和Prod环境应该不会有太大差异。这意味着为了保持一致性,您应该为两者使用相同的设置(文件系统,库等)。这样,您的大多数问题都将消失。 如果这样做,则使用硬编码路径是安全的。
其他选项(不可避免地涉及一些处理,但不应该破坏交易):
os.getcwd()
和__file__
。$SCRIPT_PATH/myscript.py PROD
),然后在脚本中基于此参数选择路径。/etc/$PROJECT_NAME
中建议),并使用特定参数运行脚本(如上文所述)。 / li>
以上方法均不能防止其他与一致性有关的问题,这使我强调您应该考虑使用Docker或Vagrant进行Dev设置(和/或Prod,如果可能)。
答案 1 :(得分:0)
当我回顾这个问题时,很明显,我提供的错误上下文可能太多,而相关的上下文却很少。在测试实际解决方案时,我决定不重写问题,而是将正确的上下文放在答案中。
大多数问题是由于以下事实:我想确定文件B相对于脚本A的路径,当时使用文件B的实际CALL使用了系统范围的模块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作为第一个参数这一事实而起作用。但是,这是我的主要用例。不确定,否则会起作用。