如何在 C++ 中调用 python 解析器来执行 python 代码(五)?

本节研究如何对 import 做白名单

目录

方法

核心内容都在这篇 CPython 接口文档

首先,实现一个 ImportInterceptor.py 文件

import sys
from importlib import abc

class UrlMetaFinder(importlib.abc.MetaPathFinder):
  def __init__(self, package_permissions):
    self.package_permissions = package_permissions

  def find_spec(self, fullname, path=None, target=None):
    if fullname in self.package_permissions:
      return None
    else:
      raise Exception(f"Package {fullname} import was not allowed")
      
def install_meta(address):
  finder = UrlMetaFinder(address)
  sys.meta_path = [finder] + sys.meta_path

然后再 C++ 文件中载入这个 python 文件:

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;

int run_py()
{
    wchar_t *program = Py_DecodeLocale("./a.out", NULL);
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    Py_Initialize();
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");
    PyRun_SimpleString("from ImportInterceptor import install_meta");
    PyRun_SimpleString("install_meta(['pandas', 'time', 'numpy'])");
    const char *script = ""
"print('Begin')\n"
"from time import time,sleep,ctime\n"
"import pandas as pd\n"
"mydataset = {\n"
"  'sites': [\"Google\", \"Runoob\", \"Wiki\"],\n"
"  'number': [1, 2, 3]\n"
"}\n"
"myvar = pd.DataFrame(mydataset)\n"
"print(myvar)\n"
"print('Today is', ctime(time()))\n";
    PyRun_SimpleString(script);
    if (Py_FinalizeEx() < 0) {
        exit(120);
    }
    PyMem_RawFree(program);
    return 0;
}

int main(int argc, char *argv[])
{
  run_py();
  return 0;

}

执行

$make
g++ -std=c++11 -I/usr/include/python3.6m -I/usr/include/python3.6m  -Wno-unused-result -Wsign-compare -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv   -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv  -L/usr/lib64 -lpython3.6m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic main.cpp


$./a.out
Begin
Traceback (most recent call last):
  File "<string>", line 3, in <module>
  File "/usr/local/lib64/python3.6/site-packages/pandas/__init__.py", line 11, in <module>
    __import__(dependency)
  File "/usr/local/lib64/python3.6/site-packages/numpy/__init__.py", line 110, in <module>
    from ._globals import ModuleDeprecationWarning, VisibleDeprecationWarning
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 951, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 894, in _find_spec
  File "./ImportInterceptor.py", line 16, in find_spec
    raise Exception(f"Package {fullname} import was not allowed")
Exception: Package numpy._globals import was not allowed

这段代码提示 numpy._globals 不允许载入。这是因为上面的 ImportInterceptor.py 做的是严格匹配,稍微改一下,改成前缀匹配:

import sys
import importlib
from importlib import abc
import urllib.request as urllib2

class UrlMetaFinder(importlib.abc.MetaPathFinder):
  def __init__(self, package_permissions):
    self.package_permissions = package_permissions

  def find_spec(self, fullname, path=None, target=None):
    if path and path[0].find('site-packages') > 0:
      print(fullname, path, target)
      if fullname.split('.')[0] in self.package_permissions:
        return None
      else:
        raise Exception(f"Package {fullname} import was not allowed")
    else:
      return None

  def find_module(self, fullname, path=None):
    print("importing module", fullname, path)
    if fullname in self.package_permissions:
      if self.package_permissions[fullname]:
        return None
      else:
        raise Exception("Package import was not allowed")
    else:
      raise Exception("Package import was not allowed")

def install_meta(address):
  finder = UrlMetaFinder(address)
  sys.meta_path = [finder] + sys.meta_path

这里只是一个例子,更进一步地,我们还可以玩出更多花样。

附录:pandas 运行 df 的情况下会动态载入库列表

pandas
numpy
numpy._globals
numpy.__config__
numpy.version
numpy._distributor_init
numpy.core
numpy.core.multiarray
numpy.core.overrides
numpy.core._multiarray_umath
numpy.compat
numpy.compat._inspect
numpy.compat.py3k
pathlib
ntpath
nt
nt
nt
pickle5
pickle
_compat_pickle
org
_pickle
numpy.core.umath
numpy.core.numerictypes
numbers
numpy.core._string_helpers
numpy.core._type_aliases
numpy.core._dtype
numpy.core.numeric
numpy.core.shape_base
numpy.core._asarray
numpy.core.fromnumeric
numpy.core._methods
numpy.core._exceptions
numpy.core._ufunc_config
numpy.core.arrayprint
numpy.core.defchararray
numpy.core.records
numpy.core.memmap
numpy.core.function_base
numpy.core.machar
numpy.core.getlimits
numpy.core.einsumfunc
numpy.core._add_newdocs
numpy.core._multiarray_tests
numpy.core._dtype_ctypes
numpy.core._internal
ast
_ast
platform
subprocess
signal
_posixsubprocess
ctypes
_ctypes
ctypes._endian
numpy._pytesttester
numpy.lib
numpy.lib.mixins
numpy.lib.scimath
numpy.lib.type_check
numpy.lib.ufunclike
numpy.lib.index_tricks
numpy.matrixlib
numpy.matrixlib.defmatrix
numpy.linalg
numpy.linalg.linalg
numpy.lib.twodim_base
numpy.linalg.lapack_lite
numpy.linalg._umath_linalg
numpy.lib.function_base
numpy.lib.histograms
numpy.lib.stride_tricks
numpy.lib.nanfunctions
numpy.lib.shape_base
numpy.lib.polynomial
numpy.lib.utils
numpy.lib.arraysetops
numpy.lib.npyio
numpy.lib.format
numpy.lib._datasource
numpy.lib._iotools
numpy.lib.financial
decimal
_decimal
numpy.lib.arrayterator
numpy.lib.arraypad
numpy.lib._version
numpy.fft
numpy.fft._pocketfft
numpy.fft._pocketfft_internal
numpy.fft.helper
numpy.polynomial
numpy.polynomial.polynomial
numpy.polynomial.polyutils
numpy.polynomial._polybase
numpy.polynomial.chebyshev
numpy.polynomial.legendre
numpy.polynomial.hermite
numpy.polynomial.hermite_e
numpy.polynomial.laguerre
numpy.random
numpy.random._pickle
numpy.random.mtrand
numpy.random.bit_generator
numpy.random._common
backports_abc
secrets
hmac
_hmacopenssl
numpy.random._bounded_integers
numpy.random._mt19937
numpy.random._philox
numpy.random._pcg64
numpy.random._sfc64
numpy.random._generator
numpy.ctypeslib
numpy.ma
numpy.ma.core
numpy.ma.extras
numpy.testing
unittest
unittest.result
unittest.util
unittest.case
difflib
logging
atexit
pprint
unittest.suite
unittest.loader
unittest.main
argparse
copy
org
gettext
unittest.runner
unittest.signals
numpy.testing._private
numpy.testing._private.utils
gc
numpy.testing._private.decorators
numpy.testing._private.nosetester
pytz
pytz.exceptions
pytz.lazy
pytz.tzinfo
pytz.tzfile
dateutil
dateutil._version
pandas.compat
pandas._typing
typing
pandas.compat.numpy
distutils
distutils.version
pandas._libs
pandas._libs.interval
pandas._libs.hashtable
pandas._libs.missing
pandas._libs.tslibs
pandas._libs.tslibs.dtypes
pandas._libs.tslibs.conversion
pandas._libs.tslibs.base
pandas._libs.tslibs.nattype
pandas._libs.tslibs.np_datetime
pandas._libs.tslibs.timezones
dateutil.tz
dateutil.tz.tz
six
__future__
six.moves
dateutil.tz._common
dateutil.tz._factories
dateutil.tz.win
six.moves.winreg
pandas._libs.tslibs.tzconversion
pandas._libs.tslibs.ccalendar
pandas._libs.tslibs.parsing
pandas._libs.tslibs.offsets
pandas._libs.tslibs.timedeltas
pandas._libs.tslibs.timestamps
backports_abc
pandas._libs.tslibs.fields
pandas._config
pandas._config.config
pandas._config.dates
pandas._config.display
pandas._config.localization
pandas._libs.tslibs.strptime
backports_abc
backports_abc
dateutil.easter
dateutil.relativedelta
dateutil._common
pandas._libs.properties
backports_abc
dateutil.parser
dateutil.parser._parser
dateutil.parser.isoparser
pandas._libs.tslibs.period
pandas._libs.tslibs.vectorized
pandas._libs.ops_dispatch
pandas._libs.algos
pandas._libs.lib
pandas._libs.tslib
pandas.core
pandas.core.config_init
pandas.core.api
pandas.core.dtypes
pandas.core.dtypes.dtypes
pandas.core.dtypes.base
pandas.errors
pandas.core.dtypes.generic
pandas.core.dtypes.inference
pandas.core.dtypes.missing
pandas.core.dtypes.common
pandas.core.algorithms
pandas.util
pandas.util._decorators
inspect
dis
opcode
_opcode
pandas.core.util
pandas.core.util.hashing
pandas._libs.hashing
pandas.core.dtypes.cast
pandas.util._validators
pandas.core.construction
pandas.core.common
pandas.core.indexers
pandas.core.arrays
pandas.core.arrays.base
pandas.compat.numpy.function
pandas.core.ops
pandas.core.ops.array_ops
pandas._libs.ops
pandas.core.ops.missing
pandas.core.ops.roperator
pandas.core.ops.dispatch
pandas.core.ops.invalid
pandas.core.ops.common
pandas.core.ops.docstrings
pandas.core.ops.mask_ops
pandas.core.ops.methods
pandas.core.missing
pandas.compat._optional
pandas.core.sorting
pandas.core.arrays.boolean
pandas.core.arrays.masked
pandas.core.nanops
bottleneck
pandas.core.array_algos
pandas.core.array_algos.masked_reductions
pandas.core.arrays.categorical
csv
_csv
pandas.core.accessor
pandas.core.array_algos.transforms
pandas.core.arrays._mixins
pandas.core.base
pandas.io
pandas.io.formats
pandas.io.formats.console
pandas.core.arrays.datetimes
pandas.core.arrays.datetimelike
pandas.tseries
pandas.tseries.frequencies
pandas.core.arrays._ranges
pandas.tseries.offsets
pandas.core.arrays.integer
pandas.core.tools
pandas.core.tools.numeric
pandas.core.arrays.interval
pandas.core.indexes
pandas.core.indexes.base
pandas._libs.index
pandas._libs.join
pandas.core.dtypes.concat
pandas.core.arrays.sparse
pandas.core.arrays.sparse.accessor
pandas.core.arrays.sparse.array
pandas._libs.sparse
pandas.core.arrays.sparse.dtype
pandas.io.formats.printing
pandas.core.indexes.frozen
pandas.core.strings
pandas.core.arrays.numpy_
pandas.core.arrays.period
pandas.core.arrays.string_
pandas.core.arrays.timedeltas
pandas.core.groupby
pandas.core.groupby.generic
pandas.core.aggregation
pandas.core.indexes.api
pandas.core.indexes.category
pandas.core.indexes.extension
pandas.core.indexes.datetimes
pandas.core.indexes.datetimelike
pandas.core.indexes.numeric
pandas.core.tools.timedeltas
pandas.core.tools.times
pandas.core.indexes.interval
pandas.util._exceptions
pandas.core.indexes.multi
pandas.core.indexes.timedeltas
pandas.core.indexes.period
pandas.core.indexes.range
pandas.core.series
pandas._libs.reshape
pandas.core.generic
json
json.decoder
json.scanner
_json
json.encoder
pandas.core.indexing
pandas._libs.indexing
pandas.core.internals
pandas.core.internals.blocks
pandas._libs.writers
pandas._libs.internals
backports_abc
pandas.core.internals.concat
pandas.core.internals.managers
pandas.core.internals.ops
pandas.core.shared_docs
pandas.io.formats.format
unicodedata
pandas.io.common
gzip
mmap
zipfile
importlib.util
pandas.core.indexes.accessors
pandas.core.tools.datetimes
pandas.arrays
pandas.plotting
pandas.plotting._core
pandas.plotting._misc
pandas.core.window
pandas.core.window.ewm
pandas._libs.window
pandas._libs.window.aggregations
pandas.core.window.common
pandas.core.groupby.base
pandas.core.window.rolling
pandas.core.util.numba_
pandas.core.window.indexers
pandas._libs.window.indexers
pandas.core.window.numba_
pandas.core.window.expanding
pandas.core.frame
pandas.core.internals.construction
pandas.core.reshape
pandas.core.reshape.melt
pandas.core.reshape.concat
pandas.core.reshape.util
pandas.io.formats.info
pandas.core.groupby.groupby
pandas._libs.groupby
pandas.core.groupby.ops
pandas._libs.reduction
pandas.core.groupby.grouper
pandas.core.groupby.categorical
pandas.tseries.api
pandas.core.computation
pandas.core.computation.api
pandas.core.computation.eval
pandas.core.computation.engines
pandas.core.computation.align
pandas.core.computation.common
pandas.core.computation.ops
pandas.core.computation.scope
pandas.compat.chainmap
pandas.core.computation.expr
pandas.core.computation.parsing
pandas.core.reshape.api
pandas.core.reshape.merge
pandas.core.reshape.pivot
pandas.core.reshape.reshape
pandas.core.reshape.tile
pandas.api
pandas.api.extensions
pandas.api.indexers
pandas.api.types
pandas.core.dtypes.api
pandas.util._print_versions
pandas.io.api
pandas.io.clipboards
pandas.io.excel
pandas.io.excel._base
pandas._libs.parsers
backports_abc
pandas.io.excel._util
pandas.io.parsers
pandas.io.date_converters
pandas.io.excel._odfreader
pandas.io.excel._openpyxl
pandas.io.excel._pyxlsb
pandas.io.excel._xlrd
pandas.io.excel._odswriter
pandas._libs.json
pandas.io.formats.excel
pandas.io.formats.css
pandas.io.excel._xlsxwriter
pandas.io.excel._xlwt
pandas.io.feather_format
pandas.io.gbq
pandas.io.html
pandas.io.json
pandas.io.json._json
pandas.io.json._normalize
pandas.io.json._table_schema
pandas.io.orc
pandas.io.parquet
pandas.io.pickle
pandas.compat.pickle_compat
pandas.io.pytables
pandas.core.computation.pytables
pandas.io.sas
pandas.io.sas.sasreader
pandas.io.spss
pandas.io.sql
pandas.io.stata
pandas.util._tester
pandas.testing
pandas._testing
pandas._libs.testing
pandas._version

其他问题

如何仅仅禁用一个包里的一个函数呢?比如,禁用 sys.exit() 怎么搞?还没有答案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C调用Python传参可以通过使用Python的C语言扩展API来实现。首先需要引入Python.h头文件,并且在C代码使用Py_Initialize()函数来初始化Python解释器。然后可以使用PyRun_SimpleString()函数来执行Python代码,通过该函数可以将Python代码作为字符串传递给Python解释器执行。 在C代码调用Python传参的具体步骤如下: 1. 引入Python的C语言扩展API头文件,如Python.h。 2. 在C代码使用Py_Initialize()函数来初始化Python解释器。 3. 使用PyRun_SimpleString()函数来执行Python代码,将Python代码作为字符串传递给该函数。 4. 在Python代码定义需要传递的参数和相关操作。 5. 在C代码使用PyArg_ParseTuple()函数来解析Python传递的参数,并将其转换为C语言的变量。 6. 在C代码进行必要的操作,并将结果返回给Python解释器。 7. 使用Py_Finalize()函数来结束Python解释器的使用。 例如,我们可以在C代码调用一个Python函数,该函数接受两个参数并返回它们的和: ```c #include <Python.h> int main(int argc, char *argv[]) { Py_Initialize(); // 初始化Python解释器 // 执行Python代码 PyRun_SimpleString("import my_module\n" "result = my_module.add(3, 5)\n" "print(result)"); // 解析Python传递的参数 int sum; PyArg_ParseTuple(args, "i", &sum); // 在C进行必要的操作 int result = sum + 10; // 返回结果给Python解释器 PyObject *pyResult = Py_BuildValue("i", result); Py_Finalize(); // 结束Python解释器 return 0; } ``` 上述代码,我们通过PyRun_SimpleString函数执行了一段Python代码,该代码导入了一个名为my_module的模块,并调用了该模块的add函数来计算3和5的和。然后在C代码,我们使用PyArg_ParseTuple函数解析了Python传递的参数,并将结果存储到sum变量。接着对sum进行了一定的操作,最后将结果通过Py_BuildValue函数转换为PyObject对象,并返回给Python解释器。 需要注意的是,在使用C调用Python传参时,需要明确了解Python的C语言扩展API的使用方法,并根据具体需求进行相应的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值