在python中打开Mongod,如何避免`shell = True`

kev*_*ham 2 python shell subprocess mongodb

我正在尝试编写一个python脚本,它将启动mongod,创建一个数据库(或打开我已经创建的数据库),添加一些信息,然后关闭mongod.

#!/usr/bin/env python

from pymongo import MongoClient
import subprocess

def create_mongo_database(database_name, path_to_database):
    mongod = subprocess.Popen(
        "mongod --dbpath {0}".format(path_to_database),
        shell=True
    )
    client = MongoClient()
    db = client[database_name]
    collection = db['test_collection']
    collection.insert_one({'something new':'some data'})
    mongod.terminate()
Run Code Online (Sandbox Code Playgroud)

这段代码有效,但是阅读python文档,他们说shell=True在子进程中使用是一个坏主意.我对这些东西很新手,而且我真的不明白shell=True旗帜在做什么,但我明白在输入变量时访问shell是不好的.问题是,当我尝试运行此删除shell=True参数时,我收到以下错误:

Traceback (most recent call last):
  File "/Users/KBLaptop/computation/kvasir/mongo_test2.py", line 23, in <module>
    create_mongo_database('test5_database', '~/computation/db')
  File "/Users/KBLaptop/computation/kvasir/mongo_test2.py", line 12, in create_mongo_database
    "mongod --dbpath {0}".format(path_to_database),
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 709, in __init__
    errread, errwrite)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1326, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
Run Code Online (Sandbox Code Playgroud)

不确定它是否重要,但在工作案例和失败案例中,我都是create_mongo_database('test5_database', '~/computation/db')在sublime text3脚本的末尾运行它.

所以我的问题是 - shell=True在这种情况下使用危险吗?如果我不这样做,为什么程序不会运行shell=True

编辑:鉴于Dano和Charles Duffy的解释,我现在将命令改为:

mongod = subprocess.Popen(
    ["mongod", "--dbpath", path_to_database],
)
Run Code Online (Sandbox Code Playgroud)

但是,如果path_to_database包含,这仍然不起作用~/.换句话说,/Users/myusername/path/to/db作品,但~/path/to/db没有.我最初的问题得到了很好的回答,我绝对可以做到这一点,不确定这个新的皱纹是否应该成为一个新问题......

Cha*_*ffy 5

实际上,我对现有的答案(建议shlex.split())表示不同意见.如果你传入一个shell引用的字符串可能包含未知数量的参数,这是有道理的 - 但在这种情况下,你确切地知道你想要多少个参数:你想要三个,从不或多或少,你想要确定这path_to_database只是一个论点.

因此,适当的使用(如果想要波浪扩展行为)是:

mongod = subprocess.Popen(['mongod', '--dbpath', os.path.expanduser(path_to_database)])
Run Code Online (Sandbox Code Playgroud)

否则,包含空格的路径将被拆分为多个参数,并且包含文字引号的路径(它们在UNIX上是合法的)将这些引号视为转义/语法而不是数据.使用shell=True会做这些事情和更多 - shlex.split()使用默认设置shell=False肯定更安全 - 但传递显式数组更好.