简体   繁体   English

Elixir:如何正确描述mix.exs设置?

[英]Elixir: How can I describe mix.exs settings correctly?

I tried to write a web scraping tool by using HTTPoison. 我尝试使用HTTPoison编写Web抓取工具。 As a first step, I wrote a short HTTP accessing code along the steps shown below; 第一步,按照下面显示的步骤编写了一个简短的HTTP访问代码。

  1. Create a project by mix 通过混合创建项目

    $ mix new httptest1 $混合新的httptest1

  2. Write a short code on lib/httptest1.ex. 在lib / httptest1.ex上写一个简短的代码。

     defmodule Httptest1 do require HTTPoison def test1 do ret = HTTPoison.get! "http://www.yahoo.com" %HTTPoison.Response{status_code: 200, body: body} = ret IO.inspect body end end Httptest1.test1() 
  3. Modify mix.exs for HTTPoison. 为HTTPoison修改mix.exs。

     defmodule Httptest1.Mixfile do use Mix.Project def project do [app: :httptest1, version: "0.0.1", elixir: "~> 1.0", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end # Configuration for the OTP application def application do [applications: [:logger, :httpoison]] end # Dependencies can be Hex packages: # defp deps do [ {:httpoison, "~> 0.6"} ] end end 
  4. Run $ mix deps.get for dependency. 运行$ mix deps.get作为依赖项。

  5. Run $ mix run , then compilation failed; 运行$ mix run ,然后编译失败;

     ==> idna (compile) Compiled src/idna.erl Compiled src/idna_ucs.erl Compiled src/punycode.erl (... snip ...) Generated httpoison app == Compilation error on file lib/httptest1.ex == ** (exit) exited in: :gen_server.call(:hackney_manager, {:new_request, #PID<0.154.0>, #Reference<0.0.1.1724>, {:client, :undefined, :hackney_dummy_metrics, :hackney_tcp_transport, 'www.yahoo.com', 80, "www.yahoo.com", [connect_timeout: 5000, recv_timeout: :infinity], nil, nil, nil, true, :hackney_pool, :infinity, false, 5, false, 5, nil, nil, nil, :undefined, :start, nil, :normal, false, false, false, false, nil, :waiting, nil, 4096, "", [], :undefined, nil, nil, nil, nil, :undefined, nil}}, :infinity) ** (EXIT) no process (stdlib) gen_server.erl:212: :gen_server.call/3 src/hackney_client/hackney_manager.erl:66: :hackney_manager.init_request/1 src/hackney_client/hackney_manager.erl:56: :hackney_manager.new_request/1 src/hackney_connect/hackney_connect.erl:181: :hackney_connect.socket_from_pool/4 src/hackney_connect/hackney_connect.erl:36: :hackney_connect.connect/5 src/hackney_client/hackney.erl:319: :hackney.request/5 lib/httpoison.ex:60: HTTPoison.request/5 lib/httpoison.ex:60: HTTPoison.request!/5 

When I used $ iex -S mix instead, the result was same. 当我改用$ iex -S mix ,结果是一样的。

But if I moved httptest1.ex to the same directory where mix.exs was placed, like $ mv lib/httptest1.ex . 但是,如果我将httptest1.ex移到了mix.exs所在的目录中,例如$ mv lib/httptest1.ex . and tried to specify the source file explicitly; 并尝试明确指定源文件; $ mix run httptest1 , it worked correctly. $ mix run httptest1 ,它可以正常工作。

Question: I suspect my mix.exs setting goes something wrong, what's that? 问题:我怀疑我的mix.exs设置出了问题,那是什么?

All .ex in lib/ are compiled. lib/中的所有.ex都已编译。 Since Elixir is meta-programming language when you compile a file you are actually running the code. 由于Elixir是编译文件时的元编程语言,因此实际上是在运行代码。 Which means that Httptest1.test1() is executed when you compile your project. 这意味着在编译项目时将执行Httptest1.test1()

HTTPoison needs to be started for it work correctly. 需要启动HTTPoison才能正常工作。 It is started when your application starts which it is when you do mix run ... . 它在您的应用程序启动时启动,而在您进行mix run ...时即启动。 But when your project is compiling your project or your dependencies are not started so calls to your dependencies might fail. 但是,当您的项目正在编译时,或者您的依赖项没有启动,因此对您的依赖项的调用可能会失败。

Check out this chapter Supervisor and Application in the getting started guide to learn how to run code when your application starts. 查阅入门指南中的本章“管理程序和应用程序” ,以了解如何在应用程序启动时运行代码。

Improved! 改进! Now I know how to create an executable invoked command line. 现在,我知道如何创建可执行文件调用的命令行了。

program; 程序;

defmodule Httptest1 do
  use Application
  require HTTPoison

  def start(_type, _args) do
    import Supervisor.Spec, warn: false
    children = []
    opts = [strategy: :one_for_one, name: Httptest1.Supervisor]
    Supervisor.start_link(children, opts)
  end

  def main(args) do # entry point
    ret = HTTPoison.get! "http://www.yahoo.com"
    %HTTPoison.Response{status_code: _, body: body} = ret # no status code matching now
    IO.inspect body
  end

end

and mix.exs (both created by $ mix new httptest1 --sup supervisor option); 和mix.exs(均由$ mix new httptest1 --sup创建$ mix new httptest1 --sup主管选项);

defmodule Httptest1.Mixfile do
  use Mix.Project

  def project do
    [app: :httptest1,
     version: "0.0.1",
     elixir: "~> 1.0",
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     escript: escript,  # <<<< Added 
     deps: deps]
  end

  def escript do # define escript 
    [main_module: Httptest1]
  end

  def application do
    [applications: [:logger, :httpoison],
     mod: {Httptest1, []}] # 
  end

  defp deps do
    [
      {:httpoison, "~> 0.6"}
    ]
  end
end

Then in the iex invoked by $ iex -S mix type Httptest.test1 , the expected result comes up! 然后在$ iex -S mix类型Httptest.test1调用的Httptest.test1 ,出现预期的结果! Thanks. 谢谢。

Also, to create command line executable, 另外,要创建命令行可执行文件,

   $ mix escript.build

then ./httptest1 is generated. 然后生成./httptest1。 Done. 完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM